{
this.iterators = iterators;
}
+ /**
+ * Returns {@code true} if the iteration has more elements. (In other words, returns {@code true} if {@link #next} would return an
+ * element rather than throwing an exception.)
+ * @return {@code true} if the iteration has more elements
+ */
@Override
public boolean hasNext() {
boolean hasNext = false;
@@ -81,6 +95,11 @@ public boolean hasNext() {
return hasNext;
}
+ /**
+ * Returns the next element in the iteration.
+ * @return the next element in the iteration
+ * @throws NoSuchElementException if the iteration has no more elements
+ */
@Override
public T next() {
if (!hasNext()) {
diff --git a/libs/common/src/main/java/org/opensearch/common/collect/Tuple.java b/libs/common/src/main/java/org/opensearch/common/collect/Tuple.java
index 36bc5504061f5..d0b94536b0729 100644
--- a/libs/common/src/main/java/org/opensearch/common/collect/Tuple.java
+++ b/libs/common/src/main/java/org/opensearch/common/collect/Tuple.java
@@ -61,6 +61,20 @@ public V2 v2() {
return v2;
}
+ /**
+ * Returns {@code true} if the given object is also a tuple and the two tuples
+ * have equal {@link #v1()} and {@link #v2()} values.
+ *
+ * Returns {@code false} otherwise, including for {@code null} values or
+ * objects of different types.
+ *
+ * Note: {@code Tuple} instances are equal if the underlying values are
+ * equal, even if the types are different.
+ *
+ * @param o the object to compare to
+ * @return {@code true} if the given object is also a tuple and the two tuples
+ * have equal {@link #v1()} and {@link #v2()} values.
+ */
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -74,6 +88,10 @@ public boolean equals(Object o) {
return true;
}
+ /**
+ * Returns the hash code value for this Tuple.
+ * @return the hash code value for this Tuple.
+ */
@Override
public int hashCode() {
int result = v1 != null ? v1.hashCode() : 0;
@@ -81,6 +99,10 @@ public int hashCode() {
return result;
}
+ /**
+ * Returns a string representation of a Tuple
+ * @return {@code "Tuple [v1=value1, v2=value2]"}
+ */
@Override
public String toString() {
return "Tuple [v1=" + v1 + ", v2=" + v2 + "]";
diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/CryptoHandler.java b/libs/common/src/main/java/org/opensearch/common/crypto/CryptoHandler.java
new file mode 100644
index 0000000000000..9572b5b9054b2
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/crypto/CryptoHandler.java
@@ -0,0 +1,118 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+package org.opensearch.common.crypto;
+
+import org.opensearch.common.annotation.ExperimentalApi;
+import org.opensearch.common.io.InputStreamContainer;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Crypto provider abstractions for encryption and decryption of data. Allows registering multiple providers
+ * for defining different ways of encrypting or decrypting data.
+ *
+ * @param Encryption Metadata / CryptoContext
+ * @param Parsed Encryption Metadata / CryptoContext
+ */
+@ExperimentalApi
+public interface CryptoHandler extends Closeable {
+
+ /**
+ * To initialise or create a new crypto metadata to be used in encryption. This is needed to set the context before
+ * beginning encryption.
+ *
+ * @return crypto metadata instance
+ */
+ T initEncryptionMetadata();
+
+ /**
+ * To load crypto metadata to be used in encryption from content header.
+ * Note that underlying information in the loaded metadata object is same as present in the object created during
+ * encryption but object type may differ.
+ *
+ * @param encryptedHeaderContentSupplier supplier for encrypted header content.
+ * @return crypto metadata instance used in decryption.
+ */
+ U loadEncryptionMetadata(EncryptedHeaderContentSupplier encryptedHeaderContentSupplier) throws IOException;
+
+ /**
+ * Few encryption algorithms have certain conditions on the unit of content to be encrypted. This requires the
+ * content size to be re adjusted in order to fulfil these conditions for partial writes. If write requests for
+ * encryption of a part of content do not fulfil these conditions then encryption fails or can result in corrupted
+ * content depending on the algorithm used. This method exposes a means to re-adjust sizes of such writes.
+ *
+ * @param cryptoContext crypto metadata instance
+ * @param contentSize Size of the raw content
+ * @return Adjusted size of the content.
+ */
+ long adjustContentSizeForPartialEncryption(T cryptoContext, long contentSize);
+
+ /**
+ * Estimate length of the encrypted content. It should only be used to determine length of entire content after
+ * encryption.
+ *
+ * @param cryptoContext crypto metadata instance consisting of encryption metadata used in encryption.
+ * @param contentLength Size of the raw content
+ * @return Calculated size of the encrypted content.
+ */
+ long estimateEncryptedLengthOfEntireContent(T cryptoContext, long contentLength);
+
+ /**
+ * For given encrypted content length, estimate the length of the decrypted content.
+ * @param cryptoContext crypto metadata instance consisting of encryption metadata used in encryption.
+ * @param contentLength Size of the encrypted content
+ * @return Calculated size of the decrypted content.
+ */
+ long estimateDecryptedLength(U cryptoContext, long contentLength);
+
+ /**
+ * Wraps a raw InputStream with encrypting stream
+ *
+ * @param encryptionMetadata created earlier to set the crypto metadata.
+ * @param stream Raw InputStream to encrypt
+ * @return encrypting stream wrapped around raw InputStream.
+ */
+ InputStreamContainer createEncryptingStream(T encryptionMetadata, InputStreamContainer stream);
+
+ /**
+ * Provides encrypted stream for a raw stream emitted for a part of content.
+ *
+ * @param cryptoContext crypto metadata instance.
+ * @param stream raw stream for which encrypted stream has to be created.
+ * @param totalStreams Number of streams being used for the entire content.
+ * @param streamIdx Index of the current stream.
+ * @return Encrypted stream for the provided raw stream.
+ */
+ InputStreamContainer createEncryptingStreamOfPart(T cryptoContext, InputStreamContainer stream, int totalStreams, int streamIdx);
+
+ /**
+ * This method accepts an encrypted stream and provides a decrypting wrapper.
+ * @param encryptingStream to be decrypted.
+ * @return Decrypting wrapper stream
+ */
+ InputStream createDecryptingStream(InputStream encryptingStream);
+
+ /**
+ * This method creates a {@link DecryptedRangedStreamProvider} which provides a wrapped stream to decrypt the
+ * underlying stream. This also provides adjusted range against the actual range which should be used for fetching
+ * and supplying the encrypted content for decryption. Extra content outside the range is trimmed down and returned
+ * by the decrypted stream.
+ * For partial reads of encrypted content, few algorithms require the range of content to be adjusted for
+ * successful decryption. Adjusted range may or may not be same as the provided range. If range is adjusted then
+ * starting offset of resultant range can be lesser than the starting offset of provided range and end
+ * offset can be greater than the ending offset of the provided range.
+ *
+ * @param cryptoContext crypto metadata instance.
+ * @param startPosOfRawContent starting position in the raw/decrypted content
+ * @param endPosOfRawContent ending position in the raw/decrypted content
+ */
+ DecryptedRangedStreamProvider createDecryptingStreamOfRange(U cryptoContext, long startPosOfRawContent, long endPosOfRawContent);
+}
diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/DataKeyPair.java b/libs/common/src/main/java/org/opensearch/common/crypto/DataKeyPair.java
new file mode 100644
index 0000000000000..711c0d314ecef
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/crypto/DataKeyPair.java
@@ -0,0 +1,45 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+package org.opensearch.common.crypto;
+
+/**
+ * Key pair generated by {@link MasterKeyProvider}
+ */
+public class DataKeyPair {
+
+ /** Unencrypted data key used for encryption and decryption */
+ private final byte[] rawKey;
+ /** Encrypted version of rawKey */
+ private final byte[] encryptedKey;
+
+ /**
+ * Constructor to initialize key-pair values
+ * @param rawKey Unencrypted data key used for encryption and decryption
+ * @param encryptedKey Encrypted version of rawKey
+ */
+ public DataKeyPair(byte[] rawKey, byte[] encryptedKey) {
+ this.rawKey = rawKey;
+ this.encryptedKey = encryptedKey;
+ }
+
+ /**
+ * Returns Unencrypted data key
+ * @return raw/decrypted key
+ */
+ public byte[] getRawKey() {
+ return rawKey;
+ }
+
+ /**
+ * Returns encrypted key
+ * @return encrypted key
+ */
+ public byte[] getEncryptedKey() {
+ return encryptedKey;
+ }
+}
diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/DecryptedRangedStreamProvider.java b/libs/common/src/main/java/org/opensearch/common/crypto/DecryptedRangedStreamProvider.java
new file mode 100644
index 0000000000000..2cda3c1f8bdb4
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/crypto/DecryptedRangedStreamProvider.java
@@ -0,0 +1,51 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+package org.opensearch.common.crypto;
+
+import java.io.InputStream;
+import java.util.function.UnaryOperator;
+
+/**
+ * Contains adjusted range of partial encrypted content which needs to be used for decryption.
+ */
+public class DecryptedRangedStreamProvider {
+
+ /** Adjusted range of partial encrypted content which needs to be used for decryption. */
+ private final long[] adjustedRange;
+ /** Stream provider for decryption and range re-adjustment. */
+ private final UnaryOperator decryptedStreamProvider;
+
+ /**
+ * To construct adjusted encrypted range.
+ * @param adjustedRange range of partial encrypted content which needs to be used for decryption.
+ * @param decryptedStreamProvider stream provider for decryption and range re-adjustment.
+ */
+ public DecryptedRangedStreamProvider(long[] adjustedRange, UnaryOperator decryptedStreamProvider) {
+ this.adjustedRange = adjustedRange;
+ this.decryptedStreamProvider = decryptedStreamProvider;
+ }
+
+ /**
+ * Adjusted range of partial encrypted content which needs to be used for decryption.
+ * @return adjusted range
+ */
+ public long[] getAdjustedRange() {
+ return adjustedRange;
+ }
+
+ /**
+ * A utility stream provider which supplies the stream responsible for decrypting the content and reading the
+ * desired range of decrypted content by skipping extra content which got decrypted as a result of range adjustment.
+ * @return stream provider for decryption and supplying the desired range of content.
+ */
+ public UnaryOperator getDecryptedStreamProvider() {
+ return decryptedStreamProvider;
+ }
+
+}
diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/EncryptedHeaderContentSupplier.java b/libs/common/src/main/java/org/opensearch/common/crypto/EncryptedHeaderContentSupplier.java
new file mode 100644
index 0000000000000..49a037f05f185
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/crypto/EncryptedHeaderContentSupplier.java
@@ -0,0 +1,25 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+package org.opensearch.common.crypto;
+
+import java.io.IOException;
+
+/**
+ * This is used in partial decryption. Header information is required for decryption of actual encrypted content.
+ * Implementation of this supplier only requires first few bytes of encrypted content to be supplied.
+ */
+public interface EncryptedHeaderContentSupplier {
+
+ /**
+ * @param start Start position of the encrypted content (Generally supplied as 0 during usage)
+ * @param end End position of the header.
+ * @return Encrypted header content (May contain additional content which is later discarded)
+ * @throws IOException In case content fetch fails.
+ */
+ byte[] supply(long start, long end) throws IOException;
+}
diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/MasterKeyProvider.java b/libs/common/src/main/java/org/opensearch/common/crypto/MasterKeyProvider.java
new file mode 100644
index 0000000000000..8afa48eb92c0f
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/crypto/MasterKeyProvider.java
@@ -0,0 +1,42 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+package org.opensearch.common.crypto;
+
+import java.io.Closeable;
+import java.util.Map;
+
+/**
+ * Master key provider responsible for management of master keys.
+ */
+public interface MasterKeyProvider extends Closeable {
+
+ /**
+ * Returns data key pair
+ * @return data key pair generated by master key.
+ */
+ DataKeyPair generateDataPair();
+
+ /**
+ * Returns decrypted key against the encrypted key.
+ * @param encryptedKey Key to decrypt
+ * @return Decrypted version of key.
+ */
+ byte[] decryptKey(byte[] encryptedKey);
+
+ /**
+ * Returns key id.
+ * @return key id
+ */
+ String getKeyId();
+
+ /**
+ * Returns encryption context associated with this master key.
+ * @return encryption context associated with this master key.
+ */
+ Map getEncryptionContext();
+}
diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/package-info.java b/libs/common/src/main/java/org/opensearch/common/crypto/package-info.java
new file mode 100644
index 0000000000000..c744689ebf532
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/crypto/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+/** Common crypto utilities used across opensearch. */
+package org.opensearch.common.crypto;
diff --git a/libs/common/src/main/java/org/opensearch/common/hash/T1ha1.java b/libs/common/src/main/java/org/opensearch/common/hash/T1ha1.java
new file mode 100644
index 0000000000000..07b2306eda4e5
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/hash/T1ha1.java
@@ -0,0 +1,277 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+package org.opensearch.common.hash;
+
+import org.opensearch.common.annotation.InternalApi;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteOrder;
+
+import static java.lang.Long.rotateRight;
+
+/**
+ * t1ha: Fast Positive Hash
+ *
+ *
+ * Implements t1ha1;
+ * a fast portable hash function with reasonable quality for checksums, hash tables, and thin fingerprinting.
+ *
+ *
+ * To overcome language and performance limitations, this implementation differs slightly from the
+ * reference implementation in C++,
+ * so the returned values may vary before JDK 18.
+ *
+ *
+ * Intended for little-endian systems but returns the same result on big-endian, albeit marginally slower.
+ *
+ * @opensearch.internal
+ */
+@InternalApi
+public final class T1ha1 {
+ private static final long SEED = System.nanoTime();
+ private static final Mux64 MUX_64_IMPL = fastestMux64Impl();
+
+ private static final VarHandle LONG_HANDLE = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN);
+ private static final VarHandle INT_HANDLE = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
+ private static final VarHandle SHORT_HANDLE = MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.LITTLE_ENDIAN);
+
+ // "Magic" primes:
+ private static final long p0 = 0xEC99BF0D8372CAABL;
+ private static final long p1 = 0x82434FE90EDCEF39L;
+ private static final long p2 = 0xD4F06DB99D67BE4BL;
+ private static final long p3 = 0xBD9CACC22C6E9571L;
+ private static final long p4 = 0x9C06FAF4D023E3ABL;
+ private static final long p5 = 0xC060724A8424F345L;
+ private static final long p6 = 0xCB5AF53AE3AAAC31L;
+
+ // Rotations:
+ private static final int s0 = 41;
+ private static final int s1 = 17;
+ private static final int s2 = 31;
+
+ /**
+ * No public constructor.
+ */
+ private T1ha1() {}
+
+ /**
+ * Returns the hash code for the specified range of the given {@code byte} array.
+ * @param input the input byte array
+ * @param offset the starting offset
+ * @param length the length of the range
+ * @return hash code
+ */
+ public static long hash(byte[] input, int offset, int length) {
+ return hash(input, offset, length, SEED);
+ }
+
+ /**
+ * Returns the hash code for the specified range of the given {@code byte} array.
+ * @param input the input byte array
+ * @param offset the starting offset
+ * @param length the length of the range
+ * @param seed customized seed
+ * @return hash code
+ */
+ public static long hash(byte[] input, int offset, int length, long seed) {
+ long a = seed;
+ long b = length;
+
+ if (length > 32) {
+ long c = rotateRight(length, s1) + seed;
+ long d = length ^ rotateRight(seed, s1);
+
+ do {
+ long w0 = fetch64(input, offset);
+ long w1 = fetch64(input, offset + 8);
+ long w2 = fetch64(input, offset + 16);
+ long w3 = fetch64(input, offset + 24);
+
+ long d02 = w0 ^ rotateRight(w2 + d, s1);
+ long c13 = w1 ^ rotateRight(w3 + c, s1);
+ c += a ^ rotateRight(w0, s0);
+ d -= b ^ rotateRight(w1, s2);
+ a ^= p1 * (d02 + w3);
+ b ^= p0 * (c13 + w2);
+
+ offset += 32;
+ length -= 32;
+ } while (length >= 32);
+
+ a ^= p6 * (rotateRight(c, s1) + d);
+ b ^= p5 * (rotateRight(d, s1) + c);
+ }
+
+ return h32(input, offset, length, a, b);
+ }
+
+ /**
+ * Computes the hash of up to 32 bytes.
+ * Constants in the switch expression are dense; JVM will use them as indices into a table of
+ * instruction pointers (tableswitch instruction), making lookups really fast.
+ */
+ @SuppressWarnings("fallthrough")
+ private static long h32(byte[] input, int offset, int length, long a, long b) {
+ switch (length) {
+ default:
+ b += mux64(fetch64(input, offset), p4);
+ offset += 8;
+ length -= 8;
+ case 24:
+ case 23:
+ case 22:
+ case 21:
+ case 20:
+ case 19:
+ case 18:
+ case 17:
+ a += mux64(fetch64(input, offset), p3);
+ offset += 8;
+ length -= 8;
+ case 16:
+ case 15:
+ case 14:
+ case 13:
+ case 12:
+ case 11:
+ case 10:
+ case 9:
+ b += mux64(fetch64(input, offset), p2);
+ offset += 8;
+ length -= 8;
+ case 8:
+ case 7:
+ case 6:
+ case 5:
+ case 4:
+ case 3:
+ case 2:
+ case 1:
+ a += mux64(tail64(input, offset, length), p1);
+ case 0:
+ // Final weak avalanche
+ return mux64(rotateRight(a + b, s1), p4) + mix64(a ^ b, p0);
+ }
+ }
+
+ /**
+ * XOR the high and low parts of the full 128-bit product.
+ */
+ private static long mux64(long a, long b) {
+ return MUX_64_IMPL.mux64(a, b);
+ }
+
+ /**
+ * XOR-MUL-XOR bit-mixer.
+ */
+ private static long mix64(long a, long b) {
+ a *= b;
+ return a ^ rotateRight(a, s0);
+ }
+
+ /**
+ * Reads "length" bytes starting at "offset" in little-endian order; returned as long.
+ * It is assumed that the length is between 1 and 8 (inclusive); but no defensive checks are made as such.
+ */
+ private static long tail64(byte[] input, int offset, int length) {
+ switch (length) {
+ case 1:
+ return fetch8(input, offset);
+ case 2:
+ return fetch16(input, offset);
+ case 3:
+ return fetch16(input, offset) | (fetch8(input, offset + 2) << 16);
+ case 4:
+ return fetch32(input, offset);
+ case 5:
+ return fetch32(input, offset) | (fetch8(input, offset + 4) << 32);
+ case 6:
+ return fetch32(input, offset) | (fetch16(input, offset + 4) << 32);
+ case 7:
+ // This is equivalent to:
+ // return fetch32(input, offset) | (fetch16(input, offset + 4) << 32) | (fetch8(input, offset + 6) << 48);
+ // But reading two ints overlapping by one byte is faster due to lesser instructions.
+ return fetch32(input, offset) | (fetch32(input, offset + 3) << 24);
+ default:
+ return fetch64(input, offset);
+ }
+ }
+
+ /**
+ * Reads a 64-bit long.
+ */
+ private static long fetch64(byte[] input, int offset) {
+ return (long) LONG_HANDLE.get(input, offset);
+ }
+
+ /**
+ * Reads a 32-bit unsigned integer, returned as long.
+ */
+ private static long fetch32(byte[] input, int offset) {
+ return (int) INT_HANDLE.get(input, offset) & 0xFFFFFFFFL;
+ }
+
+ /**
+ * Reads a 16-bit unsigned short, returned as long.
+ */
+ private static long fetch16(byte[] input, int offset) {
+ return (short) SHORT_HANDLE.get(input, offset) & 0xFFFFL;
+ }
+
+ /**
+ * Reads an 8-bit unsigned byte, returned as long.
+ */
+ private static long fetch8(byte[] input, int offset) {
+ return input[offset] & 0xFFL;
+ }
+
+ /**
+ * The implementation of mux64.
+ */
+ @FunctionalInterface
+ private interface Mux64 {
+ long mux64(long a, long b);
+ }
+
+ /**
+ * Provides the fastest available implementation of mux64 on this platform.
+ *
+ *
+ * Ideally, the following should be returned to match the reference implementation:
+ * {@code Math.unsignedMultiplyHigh(a, b) ^ (a * b)}
+ *
+ *
+ * Since unsignedMultiplyHigh isn't available before JDK 18, and calculating it without intrinsics is quite slow,
+ * the multiplyHigh method is used instead. Slight loss in quality is imperceptible for our use-case: a hash table.
+ * {@code Math.multiplyHigh(a, b) ^ (a * b)}
+ *
+ *
+ * This indirection can be removed once we stop supporting older JDKs.
+ */
+ private static Mux64 fastestMux64Impl() {
+ try {
+ final MethodHandle unsignedMultiplyHigh = MethodHandles.publicLookup()
+ .findStatic(Math.class, "unsignedMultiplyHigh", MethodType.methodType(long.class, long.class, long.class));
+ return (a, b) -> {
+ try {
+ return (long) unsignedMultiplyHigh.invokeExact(a, b) ^ (a * b);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ };
+ } catch (NoSuchMethodException e) {
+ return (a, b) -> Math.multiplyHigh(a, b) ^ (a * b);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/server/src/main/java/org/opensearch/common/component/package-info.java b/libs/common/src/main/java/org/opensearch/common/hash/package-info.java
similarity index 71%
rename from server/src/main/java/org/opensearch/common/component/package-info.java
rename to libs/common/src/main/java/org/opensearch/common/hash/package-info.java
index 34d034b5a3ffb..bd393b8b921ed 100644
--- a/server/src/main/java/org/opensearch/common/component/package-info.java
+++ b/libs/common/src/main/java/org/opensearch/common/hash/package-info.java
@@ -6,5 +6,7 @@
* compatible open source license.
*/
-/** Base Lifecycle Component package. */
-package org.opensearch.common.component;
+/**
+ * Common hashing utilities.
+ */
+package org.opensearch.common.hash;
diff --git a/server/src/main/java/org/opensearch/common/component/AbstractLifecycleComponent.java b/libs/common/src/main/java/org/opensearch/common/lifecycle/AbstractLifecycleComponent.java
similarity index 98%
rename from server/src/main/java/org/opensearch/common/component/AbstractLifecycleComponent.java
rename to libs/common/src/main/java/org/opensearch/common/lifecycle/AbstractLifecycleComponent.java
index 837f8af44bf13..111556fbe43cf 100644
--- a/server/src/main/java/org/opensearch/common/component/AbstractLifecycleComponent.java
+++ b/libs/common/src/main/java/org/opensearch/common/lifecycle/AbstractLifecycleComponent.java
@@ -30,7 +30,7 @@
* GitHub history for details.
*/
-package org.opensearch.common.component;
+package org.opensearch.common.lifecycle;
import java.io.IOException;
import java.io.UncheckedIOException;
diff --git a/server/src/main/java/org/opensearch/common/component/Lifecycle.java b/libs/common/src/main/java/org/opensearch/common/lifecycle/Lifecycle.java
similarity index 97%
rename from server/src/main/java/org/opensearch/common/component/Lifecycle.java
rename to libs/common/src/main/java/org/opensearch/common/lifecycle/Lifecycle.java
index fb12c1fc9ac4b..c1cf9b2998a13 100644
--- a/server/src/main/java/org/opensearch/common/component/Lifecycle.java
+++ b/libs/common/src/main/java/org/opensearch/common/lifecycle/Lifecycle.java
@@ -30,7 +30,9 @@
* GitHub history for details.
*/
-package org.opensearch.common.component;
+package org.opensearch.common.lifecycle;
+
+import org.opensearch.common.annotation.PublicApi;
/**
* Lifecycle state. Allows the following transitions:
@@ -73,15 +75,17 @@
* }
*
*
- * @opensearch.internal
+ * @opensearch.api
*/
+@PublicApi(since = "1.0.0")
public class Lifecycle {
/**
* State in the lifecycle
*
- * @opensearch.internal
+ * @opensearch.api
*/
+ @PublicApi(since = "1.0.0")
public enum State {
INITIALIZED,
STOPPED,
diff --git a/server/src/main/java/org/opensearch/common/component/LifecycleComponent.java b/libs/common/src/main/java/org/opensearch/common/lifecycle/LifecycleComponent.java
similarity index 91%
rename from server/src/main/java/org/opensearch/common/component/LifecycleComponent.java
rename to libs/common/src/main/java/org/opensearch/common/lifecycle/LifecycleComponent.java
index 984d55df1bdfa..781c276fefe13 100644
--- a/server/src/main/java/org/opensearch/common/component/LifecycleComponent.java
+++ b/libs/common/src/main/java/org/opensearch/common/lifecycle/LifecycleComponent.java
@@ -30,15 +30,17 @@
* GitHub history for details.
*/
-package org.opensearch.common.component;
+package org.opensearch.common.lifecycle;
+import org.opensearch.common.annotation.PublicApi;
import org.opensearch.common.lease.Releasable;
/**
* Base interface for a lifecycle component.
*
- * @opensearch.internal
+ * @opensearch.api
*/
+@PublicApi(since = "1.0.0")
public interface LifecycleComponent extends Releasable {
Lifecycle.State lifecycleState();
diff --git a/server/src/main/java/org/opensearch/common/component/LifecycleListener.java b/libs/common/src/main/java/org/opensearch/common/lifecycle/LifecycleListener.java
similarity index 97%
rename from server/src/main/java/org/opensearch/common/component/LifecycleListener.java
rename to libs/common/src/main/java/org/opensearch/common/lifecycle/LifecycleListener.java
index 89c344b955bc9..7ac41a5eb0df0 100644
--- a/server/src/main/java/org/opensearch/common/component/LifecycleListener.java
+++ b/libs/common/src/main/java/org/opensearch/common/lifecycle/LifecycleListener.java
@@ -30,7 +30,7 @@
* GitHub history for details.
*/
-package org.opensearch.common.component;
+package org.opensearch.common.lifecycle;
/**
* Base lifecycle listener.
diff --git a/libs/common/src/main/java/org/opensearch/common/lifecycle/package-info.java b/libs/common/src/main/java/org/opensearch/common/lifecycle/package-info.java
new file mode 100644
index 0000000000000..1bedde5585e36
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/lifecycle/package-info.java
@@ -0,0 +1,16 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+/**
+ * Foundation implementation for a object lifecycle.
+ *
+ * See {@link org.opensearch.common.lifecycle.Lifecycle} for example usage
+ *
+ * @opensearch.internal
+ */
+package org.opensearch.common.lifecycle;
diff --git a/server/src/main/java/org/opensearch/common/network/Cidrs.java b/libs/common/src/main/java/org/opensearch/common/network/Cidrs.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/network/Cidrs.java
rename to libs/common/src/main/java/org/opensearch/common/network/Cidrs.java
diff --git a/server/src/main/java/org/opensearch/common/network/InetAddresses.java b/libs/common/src/main/java/org/opensearch/common/network/InetAddresses.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/network/InetAddresses.java
rename to libs/common/src/main/java/org/opensearch/common/network/InetAddresses.java
diff --git a/server/src/main/java/org/opensearch/common/network/NetworkAddress.java b/libs/common/src/main/java/org/opensearch/common/network/NetworkAddress.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/network/NetworkAddress.java
rename to libs/common/src/main/java/org/opensearch/common/network/NetworkAddress.java
diff --git a/libs/common/src/main/java/org/opensearch/common/network/package-info.java b/libs/common/src/main/java/org/opensearch/common/network/package-info.java
new file mode 100644
index 0000000000000..92e4eac5bde42
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/network/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+/** common network layer classes used across the code base */
+package org.opensearch.common.network;
diff --git a/server/src/main/java/org/opensearch/common/recycler/AbstractRecycler.java b/libs/common/src/main/java/org/opensearch/common/recycler/AbstractRecycler.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/recycler/AbstractRecycler.java
rename to libs/common/src/main/java/org/opensearch/common/recycler/AbstractRecycler.java
diff --git a/server/src/main/java/org/opensearch/common/recycler/AbstractRecyclerC.java b/libs/common/src/main/java/org/opensearch/common/recycler/AbstractRecyclerC.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/recycler/AbstractRecyclerC.java
rename to libs/common/src/main/java/org/opensearch/common/recycler/AbstractRecyclerC.java
diff --git a/server/src/main/java/org/opensearch/common/recycler/ConcurrentDequeRecycler.java b/libs/common/src/main/java/org/opensearch/common/recycler/ConcurrentDequeRecycler.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/recycler/ConcurrentDequeRecycler.java
rename to libs/common/src/main/java/org/opensearch/common/recycler/ConcurrentDequeRecycler.java
diff --git a/server/src/main/java/org/opensearch/common/recycler/DequeRecycler.java b/libs/common/src/main/java/org/opensearch/common/recycler/DequeRecycler.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/recycler/DequeRecycler.java
rename to libs/common/src/main/java/org/opensearch/common/recycler/DequeRecycler.java
diff --git a/server/src/main/java/org/opensearch/common/recycler/FilterRecycler.java b/libs/common/src/main/java/org/opensearch/common/recycler/FilterRecycler.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/recycler/FilterRecycler.java
rename to libs/common/src/main/java/org/opensearch/common/recycler/FilterRecycler.java
diff --git a/server/src/main/java/org/opensearch/common/recycler/NoneRecycler.java b/libs/common/src/main/java/org/opensearch/common/recycler/NoneRecycler.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/recycler/NoneRecycler.java
rename to libs/common/src/main/java/org/opensearch/common/recycler/NoneRecycler.java
diff --git a/server/src/main/java/org/opensearch/common/recycler/Recycler.java b/libs/common/src/main/java/org/opensearch/common/recycler/Recycler.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/recycler/Recycler.java
rename to libs/common/src/main/java/org/opensearch/common/recycler/Recycler.java
diff --git a/server/src/main/java/org/opensearch/common/recycler/Recyclers.java b/libs/common/src/main/java/org/opensearch/common/recycler/Recyclers.java
similarity index 98%
rename from server/src/main/java/org/opensearch/common/recycler/Recyclers.java
rename to libs/common/src/main/java/org/opensearch/common/recycler/Recyclers.java
index 4cbb80509d6a1..52587144369f1 100644
--- a/server/src/main/java/org/opensearch/common/recycler/Recyclers.java
+++ b/libs/common/src/main/java/org/opensearch/common/recycler/Recyclers.java
@@ -75,6 +75,8 @@ public static Recycler.Factory dequeFactory(final Recycler.C c, final
/**
* Wrap the provided recycler so that calls to {@link Recycler#obtain()} and {@link Recycler.V#close()} are protected by
* a lock.
+ *
+ * @opensearch.internal
*/
public static Recycler locked(final Recycler recycler) {
return new FilterRecycler() {
@@ -140,7 +142,7 @@ public static Recycler concurrent(final Recycler.Factory factory, fina
private final Recycler[] recyclers;
{
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({ "rawtypes", "unchecked" })
final Recycler[] recyclers = new Recycler[concurrencyLevel];
this.recyclers = recyclers;
for (int i = 0; i < concurrencyLevel; ++i) {
diff --git a/libs/common/src/main/java/org/opensearch/common/recycler/package-info.java b/libs/common/src/main/java/org/opensearch/common/recycler/package-info.java
new file mode 100644
index 0000000000000..fec3c5d5e52d3
--- /dev/null
+++ b/libs/common/src/main/java/org/opensearch/common/recycler/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+/** Common Recycler functionality for recycling objects */
+package org.opensearch.common.recycler;
diff --git a/server/src/main/java/org/opensearch/common/transport/NetworkExceptionHelper.java b/libs/common/src/main/java/org/opensearch/common/transport/NetworkExceptionHelper.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/transport/NetworkExceptionHelper.java
rename to libs/common/src/main/java/org/opensearch/common/transport/NetworkExceptionHelper.java
diff --git a/server/src/main/java/org/opensearch/common/transport/PortsRange.java b/libs/common/src/main/java/org/opensearch/common/transport/PortsRange.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/transport/PortsRange.java
rename to libs/common/src/main/java/org/opensearch/common/transport/PortsRange.java
diff --git a/server/src/main/java/org/opensearch/common/transport/package-info.java b/libs/common/src/main/java/org/opensearch/common/transport/package-info.java
similarity index 79%
rename from server/src/main/java/org/opensearch/common/transport/package-info.java
rename to libs/common/src/main/java/org/opensearch/common/transport/package-info.java
index abb8dfbb4e4f0..7d28ac6c60a14 100644
--- a/server/src/main/java/org/opensearch/common/transport/package-info.java
+++ b/libs/common/src/main/java/org/opensearch/common/transport/package-info.java
@@ -6,5 +6,5 @@
* compatible open source license.
*/
-/** Base Transport utility package. */
+/** common transport layer classes used across the code base */
package org.opensearch.common.transport;
diff --git a/libs/common/src/main/java/org/opensearch/common/unit/TimeValue.java b/libs/common/src/main/java/org/opensearch/common/unit/TimeValue.java
index 670275397893c..a3fcffb1d6a4c 100644
--- a/libs/common/src/main/java/org/opensearch/common/unit/TimeValue.java
+++ b/libs/common/src/main/java/org/opensearch/common/unit/TimeValue.java
@@ -32,6 +32,8 @@
package org.opensearch.common.unit;
+import org.opensearch.common.annotation.PublicApi;
+
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@@ -41,6 +43,7 @@
*
* @opensearch.api
*/
+@PublicApi(since = "1.0.0")
public class TimeValue implements Comparable {
/** How many nano-seconds in one milli-second */
diff --git a/server/src/main/java/org/opensearch/common/util/concurrent/ConcurrentCollections.java b/libs/common/src/main/java/org/opensearch/common/util/concurrent/ConcurrentCollections.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/util/concurrent/ConcurrentCollections.java
rename to libs/common/src/main/java/org/opensearch/common/util/concurrent/ConcurrentCollections.java
diff --git a/server/src/main/java/org/opensearch/common/util/concurrent/ConcurrentHashMapLong.java b/libs/common/src/main/java/org/opensearch/common/util/concurrent/ConcurrentHashMapLong.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/util/concurrent/ConcurrentHashMapLong.java
rename to libs/common/src/main/java/org/opensearch/common/util/concurrent/ConcurrentHashMapLong.java
diff --git a/server/src/main/java/org/opensearch/common/util/concurrent/ConcurrentMapLong.java b/libs/common/src/main/java/org/opensearch/common/util/concurrent/ConcurrentMapLong.java
similarity index 100%
rename from server/src/main/java/org/opensearch/common/util/concurrent/ConcurrentMapLong.java
rename to libs/common/src/main/java/org/opensearch/common/util/concurrent/ConcurrentMapLong.java
diff --git a/server/src/test/java/org/opensearch/common/collect/IteratorsTests.java b/libs/common/src/test/java/org/opensearch/common/collect/IteratorsTests.java
similarity index 98%
rename from server/src/test/java/org/opensearch/common/collect/IteratorsTests.java
rename to libs/common/src/test/java/org/opensearch/common/collect/IteratorsTests.java
index 6ad272542dbb1..2578926454c0b 100644
--- a/server/src/test/java/org/opensearch/common/collect/IteratorsTests.java
+++ b/libs/common/src/test/java/org/opensearch/common/collect/IteratorsTests.java
@@ -83,6 +83,7 @@ public void testRandomSingleton() {
int numberOfIterators = randomIntBetween(1, 1000);
int singletonIndex = randomIntBetween(0, numberOfIterators - 1);
int value = randomInt();
+ @SuppressWarnings("rawtypes")
Iterator[] iterators = new Iterator[numberOfIterators];
for (int i = 0; i < numberOfIterators; i++) {
iterators[i] = i != singletonIndex ? empty() : singletonIterator(value);
@@ -92,6 +93,7 @@ public void testRandomSingleton() {
public void testRandomIterators() {
int numberOfIterators = randomIntBetween(1, 1000);
+ @SuppressWarnings("rawtypes")
Iterator[] iterators = new Iterator[numberOfIterators];
List values = new ArrayList<>();
for (int i = 0; i < numberOfIterators; i++) {
diff --git a/libs/common/src/test/java/org/opensearch/common/hash/T1Ha1Tests.java b/libs/common/src/test/java/org/opensearch/common/hash/T1Ha1Tests.java
new file mode 100644
index 0000000000000..e348fbf759bdd
--- /dev/null
+++ b/libs/common/src/test/java/org/opensearch/common/hash/T1Ha1Tests.java
@@ -0,0 +1,312 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+package org.opensearch.common.hash;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteOrder;
+
+public class T1Ha1Tests extends HashFunctionTestCase {
+ private static final VarHandle LONG_HANDLE = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN);
+ private final byte[] scratch = new byte[8];
+
+ /**
+ * Inspired from the tests defined in the reference implementation:
+ * t1ha_selfcheck.c
+ */
+ public void testSelfCheck() {
+ byte[] testPattern = {
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ (byte) 0xFF,
+ 0x7F,
+ 0x3F,
+ 0x1F,
+ 0xF,
+ 8,
+ 16,
+ 32,
+ 64,
+ (byte) 0x80,
+ (byte) 0xFE,
+ (byte) 0xFC,
+ (byte) 0xF8,
+ (byte) 0xF0,
+ (byte) 0xE0,
+ (byte) 0xC0,
+ (byte) 0xFD,
+ (byte) 0xFB,
+ (byte) 0xF7,
+ (byte) 0xEF,
+ (byte) 0xDF,
+ (byte) 0xBF,
+ 0x55,
+ (byte) 0xAA,
+ 11,
+ 17,
+ 19,
+ 23,
+ 29,
+ 37,
+ 42,
+ 43,
+ 'a',
+ 'b',
+ 'c',
+ 'd',
+ 'e',
+ 'f',
+ 'g',
+ 'h',
+ 'i',
+ 'j',
+ 'k',
+ 'l',
+ 'm',
+ 'n',
+ 'o',
+ 'p',
+ 'q',
+ 'r',
+ 's',
+ 't',
+ 'u',
+ 'v',
+ 'w',
+ 'x' };
+
+ // Reference hashes when using {@link Math::unsignedMultiplyHigh} in the mux64 step.
+ // These values match the ones defined in the reference implementation:
+ // https://github.com/erthink/t1ha/blob/master/src/t1ha1_selfcheck.c#L51-L72
+ long[] referenceUnsignedMultiplyHigh = {
+ 0L,
+ 0x6A580668D6048674L,
+ 0xA2FE904AFF0D0879L,
+ 0xE3AB9C06FAF4D023L,
+ 0x6AF1C60874C95442L,
+ 0xB3557E561A6C5D82L,
+ 0x0AE73C696F3D37C0L,
+ 0x5EF25F7062324941L,
+ 0x9B784F3B4CE6AF33L,
+ 0x6993BB206A74F070L,
+ 0xF1E95DF109076C4CL,
+ 0x4E1EB70C58E48540L,
+ 0x5FDD7649D8EC44E4L,
+ 0x559122C706343421L,
+ 0x380133D58665E93DL,
+ 0x9CE74296C8C55AE4L,
+ 0x3556F9A5757AB6D0L,
+ 0xF62751F7F25C469EL,
+ 0x851EEC67F6516D94L,
+ 0xED463EE3848A8695L,
+ 0xDC8791FEFF8ED3ACL,
+ 0x2569C744E1A282CFL,
+ 0xF90EB7C1D70A80B9L,
+ 0x68DFA6A1B8050A4CL,
+ 0x94CCA5E8210D2134L,
+ 0xF5CC0BEABC259F52L,
+ 0x40DBC1F51618FDA7L,
+ 0x0807945BF0FB52C6L,
+ 0xE5EF7E09DE70848DL,
+ 0x63E1DF35FEBE994AL,
+ 0x2025E73769720D5AL,
+ 0xAD6120B2B8A152E1L,
+ 0x2A71D9F13959F2B7L,
+ 0x8A20849A27C32548L,
+ 0x0BCBC9FE3B57884EL,
+ 0x0E028D255667AEADL,
+ 0xBE66DAD3043AB694L,
+ 0xB00E4C1238F9E2D4L,
+ 0x5C54BDE5AE280E82L,
+ 0x0E22B86754BC3BC4L,
+ 0x016707EBF858B84DL,
+ 0x990015FBC9E095EEL,
+ 0x8B9AF0A3E71F042FL,
+ 0x6AA56E88BD380564L,
+ 0xAACE57113E681A0FL,
+ 0x19F81514AFA9A22DL,
+ 0x80DABA3D62BEAC79L,
+ 0x715210412CABBF46L,
+ 0xD8FA0B9E9D6AA93FL,
+ 0x6C2FC5A4109FD3A2L,
+ 0x5B3E60EEB51DDCD8L,
+ 0x0A7C717017756FE7L,
+ 0xA73773805CA31934L,
+ 0x4DBD6BB7A31E85FDL,
+ 0x24F619D3D5BC2DB4L,
+ 0x3E4AF35A1678D636L,
+ 0x84A1A8DF8D609239L,
+ 0x359C862CD3BE4FCDL,
+ 0xCF3A39F5C27DC125L,
+ 0xC0FF62F8FD5F4C77L,
+ 0x5E9F2493DDAA166CL,
+ 0x17424152BE1CA266L,
+ 0xA78AFA5AB4BBE0CDL,
+ 0x7BFB2E2CEF118346L,
+ 0x647C3E0FF3E3D241L,
+ 0x0352E4055C13242EL,
+ 0x6F42FC70EB660E38L,
+ 0x0BEBAD4FABF523BAL,
+ 0x9269F4214414D61DL,
+ 0x1CA8760277E6006CL,
+ 0x7BAD25A859D87B5DL,
+ 0xAD645ADCF7414F1DL,
+ 0xB07F517E88D7AFB3L,
+ 0xB321C06FB5FFAB5CL,
+ 0xD50F162A1EFDD844L,
+ 0x1DFD3D1924FBE319L,
+ 0xDFAEAB2F09EF7E78L,
+ 0xA7603B5AF07A0B1EL,
+ 0x41CD044C0E5A4EE3L,
+ 0xF64D2F86E813BF33L,
+ 0xFF9FDB99305EB06AL };
+
+ // Reference hashes when using {@link Math::multiplyHigh} in the mux64 step.
+ long[] referenceMultiplyHigh = {
+ 0L,
+ 0xCE510B7405E0A2CAL,
+ 0xC0A2DA74A8271FCBL,
+ 0x1C549C06FAF4D023L,
+ 0x084CDA0ED41CD2D4L,
+ 0xD05BA7AA9FEECE5BL,
+ 0x7D6128AB2CCC4EB1L,
+ 0x62332FA6EC1B50AAL,
+ 0x1B66C81767870EF2L,
+ 0xEC6B92A37AED73B8L,
+ 0x1712987232EF4ED3L,
+ 0xAA503A04AE2450B5L,
+ 0x15D25DE445730A6CL,
+ 0xAB87E38AA8D21746L,
+ 0x18CAE735BBF62D15L,
+ 0x0D56DFF9914CA656L,
+ 0xCB4F5859A9AE5B52L,
+ 0xEE97003F7B1283E1L,
+ 0x50CFB2AF0F54BA6DL,
+ 0x570B4D6AE4C67814L,
+ 0x1ED59274A97497EBL,
+ 0x8608D03D165C59BFL,
+ 0x6CBE0E537BE04C02L,
+ 0xD4C8FCFD4179A874L,
+ 0xFB4E677D876118A1L,
+ 0x6B1A96F1B4765D79L,
+ 0x1075B9B89BDFE5F8L,
+ 0x02771D08F2891CB1L,
+ 0x4BB8E16FF410F19EL,
+ 0x3EB7849C0DFAF566L,
+ 0x173B09359DE422CFL,
+ 0xFE212C6DB7474306L,
+ 0xA74E7C2D632664EFL,
+ 0x56ECDED6546F0914L,
+ 0x08DEF866EF20A94BL,
+ 0x7D0BAC64606521F1L,
+ 0xCA6BA9817A357FA9L,
+ 0x0873B834A6E2AAE4L,
+ 0x45EE02D6DCF8992EL,
+ 0x3EA060225B3E1C1FL,
+ 0x24DBB6D02D5CC531L,
+ 0xE5E91A7340BF9382L,
+ 0x28975F86E2E2177FL,
+ 0x80E48374A6B42E85L,
+ 0xDF40392265BB4A66L,
+ 0x43750475A48C7023L,
+ 0x5648BD3E391C01D3L,
+ 0x9BE9E11AD1A6C369L,
+ 0x2E079CB8C1A11F50L,
+ 0xB2D538403F1020F1L,
+ 0x297518A4EF6AF5F1L,
+ 0xA8CE1B90167A6F8BL,
+ 0xB926B2FA50541BA9L,
+ 0xC46A2D3BD6925A35L,
+ 0x3071BC8E6C400487L,
+ 0x300D3885894BA47FL,
+ 0x840BFF3BEB7EEADDL,
+ 0xDC9E04DF744BDC0CL,
+ 0xBE01CF6841412C77L,
+ 0x6C55B2DC74B816A1L,
+ 0x4D4C63128A344F82L,
+ 0xC6227497E100B463L,
+ 0x53C9987705EA71C0L,
+ 0x3E355394668C3559L,
+ 0x05984B7D358B107AL,
+ 0x4D32FA1D79002A57L,
+ 0x910B0DAD1440EC24L,
+ 0x025BDE6A7BEBF320L,
+ 0x0D33817EF345D999L,
+ 0xBA0DE64B3F4DB34AL,
+ 0x54666461D0EB4FD7L,
+ 0x746ECFA92D1CAF81L,
+ 0x6E6A774ACD266DF2L,
+ 0x1A86161AE8E82A85L,
+ 0xFFF7C351A4CEC13DL,
+ 0xFFF05844F57498B8L,
+ 0x8DB71789127C6C13L,
+ 0x4A52ACF805F370ABL,
+ 0xFE13F90A1ACFBD58L,
+ 0x615730E301ED12E2L,
+ 0x1A2D4AA43B6C0103L };
+
+ long[] reference = hasUnsignedMultiplyHigh() ? referenceUnsignedMultiplyHigh : referenceMultiplyHigh;
+
+ int offset = 0;
+ assertEquals(reference[offset++], T1ha1.hash(null, 0, 0, 0L)); // empty-zero
+ assertEquals(reference[offset++], T1ha1.hash(null, 0, 0, ~0L)); // empty-all1
+ assertEquals(reference[offset++], T1ha1.hash(testPattern, 0, 64, 0L)); // bin64-zero
+
+ long seed = 1;
+ for (int i = 1; i < 64; i++) {
+ assertEquals(reference[offset++], T1ha1.hash(testPattern, 0, i, seed)); // bin%i-1p%i
+ seed <<= 1;
+ }
+
+ seed = ~0L;
+ for (int i = 1; i <= 7; i++) {
+ seed <<= 1;
+ assertEquals(reference[offset++], T1ha1.hash(testPattern, i, 64 - i, seed)); // align%i_F%i
+ }
+
+ byte[] testPatternLong = new byte[512];
+ for (int i = 0; i < testPatternLong.length; i++) {
+ testPatternLong[i] = (byte) i;
+ }
+ for (int i = 0; i <= 7; i++) {
+ assertEquals(reference[offset++], T1ha1.hash(testPatternLong, i, 128 + i * 17, seed)); // long-%05i
+ }
+ }
+
+ @Override
+ public byte[] hash(byte[] input) {
+ long hash = T1ha1.hash(input, 0, input.length);
+ LONG_HANDLE.set(scratch, 0, hash);
+ return scratch;
+ }
+
+ @Override
+ public int outputBits() {
+ return 64;
+ }
+
+ private static boolean hasUnsignedMultiplyHigh() {
+ try {
+ MethodHandles.publicLookup()
+ .findStatic(Math.class, "unsignedMultiplyHigh", MethodType.methodType(long.class, long.class, long.class));
+ return true;
+ } catch (NoSuchMethodException e) {
+ return false;
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/server/src/test/java/org/opensearch/common/network/CidrsTests.java b/libs/common/src/test/java/org/opensearch/common/network/CidrsTests.java
similarity index 100%
rename from server/src/test/java/org/opensearch/common/network/CidrsTests.java
rename to libs/common/src/test/java/org/opensearch/common/network/CidrsTests.java
diff --git a/server/src/test/java/org/opensearch/common/network/InetAddressesTests.java b/libs/common/src/test/java/org/opensearch/common/network/InetAddressesTests.java
similarity index 100%
rename from server/src/test/java/org/opensearch/common/network/InetAddressesTests.java
rename to libs/common/src/test/java/org/opensearch/common/network/InetAddressesTests.java
diff --git a/server/src/test/java/org/opensearch/common/network/NetworkAddressTests.java b/libs/common/src/test/java/org/opensearch/common/network/NetworkAddressTests.java
similarity index 100%
rename from server/src/test/java/org/opensearch/common/network/NetworkAddressTests.java
rename to libs/common/src/test/java/org/opensearch/common/network/NetworkAddressTests.java
diff --git a/server/src/test/java/org/opensearch/common/recycler/AbstractRecyclerTestCase.java b/libs/common/src/test/java/org/opensearch/common/recycler/AbstractRecyclerTestCase.java
similarity index 100%
rename from server/src/test/java/org/opensearch/common/recycler/AbstractRecyclerTestCase.java
rename to libs/common/src/test/java/org/opensearch/common/recycler/AbstractRecyclerTestCase.java
diff --git a/server/src/test/java/org/opensearch/common/recycler/ConcurrentRecyclerTests.java b/libs/common/src/test/java/org/opensearch/common/recycler/ConcurrentRecyclerTests.java
similarity index 100%
rename from server/src/test/java/org/opensearch/common/recycler/ConcurrentRecyclerTests.java
rename to libs/common/src/test/java/org/opensearch/common/recycler/ConcurrentRecyclerTests.java
diff --git a/server/src/test/java/org/opensearch/common/recycler/LockedRecyclerTests.java b/libs/common/src/test/java/org/opensearch/common/recycler/LockedRecyclerTests.java
similarity index 100%
rename from server/src/test/java/org/opensearch/common/recycler/LockedRecyclerTests.java
rename to libs/common/src/test/java/org/opensearch/common/recycler/LockedRecyclerTests.java
diff --git a/server/src/test/java/org/opensearch/common/recycler/NoneRecyclerTests.java b/libs/common/src/test/java/org/opensearch/common/recycler/NoneRecyclerTests.java
similarity index 100%
rename from server/src/test/java/org/opensearch/common/recycler/NoneRecyclerTests.java
rename to libs/common/src/test/java/org/opensearch/common/recycler/NoneRecyclerTests.java
diff --git a/server/src/test/java/org/opensearch/common/recycler/QueueRecyclerTests.java b/libs/common/src/test/java/org/opensearch/common/recycler/QueueRecyclerTests.java
similarity index 100%
rename from server/src/test/java/org/opensearch/common/recycler/QueueRecyclerTests.java
rename to libs/common/src/test/java/org/opensearch/common/recycler/QueueRecyclerTests.java
diff --git a/libs/compress/build.gradle b/libs/compress/build.gradle
new file mode 100644
index 0000000000000..7a5bc2f573dea
--- /dev/null
+++ b/libs/compress/build.gradle
@@ -0,0 +1,38 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ *
+ * Modifications Copyright OpenSearch Contributors. See
+ * GitHub history for details.
+ */
+
+apply plugin: 'opensearch.build'
+apply plugin: 'opensearch.publish'
+
+base {
+ archivesName = 'opensearch-compress'
+}
+
+dependencies {
+ api project(':libs:opensearch-common')
+ api project(':libs:opensearch-core')
+
+ //zstd
+ api "com.github.luben:zstd-jni:${versions.zstd}"
+
+ testImplementation(project(":test:framework")) {
+ // tests use the locally compiled version of server
+ exclude group: 'org.opensearch', module: 'opensearch-compress'
+ }
+}
+
+tasks.named('forbiddenApisMain').configure {
+ // :libs:opensearch-compress does not depend on server
+ // TODO: Need to decide how we want to handle for forbidden signatures with the changes to server
+ replaceSignatureFiles 'jdk-signatures'
+}
+
+jarHell.enabled = false
diff --git a/libs/compress/licenses/zstd-jni-1.5.5-5.jar.sha1 b/libs/compress/licenses/zstd-jni-1.5.5-5.jar.sha1
new file mode 100644
index 0000000000000..498c60c34e3da
--- /dev/null
+++ b/libs/compress/licenses/zstd-jni-1.5.5-5.jar.sha1
@@ -0,0 +1 @@
+74ffdc5f140080adacf5278287aadd950179f848
\ No newline at end of file
diff --git a/server/licenses/zstd-jni-LICENSE.txt b/libs/compress/licenses/zstd-jni-LICENSE.txt
similarity index 100%
rename from server/licenses/zstd-jni-LICENSE.txt
rename to libs/compress/licenses/zstd-jni-LICENSE.txt
diff --git a/server/licenses/zstd-jni-NOTICE.txt b/libs/compress/licenses/zstd-jni-NOTICE.txt
similarity index 100%
rename from server/licenses/zstd-jni-NOTICE.txt
rename to libs/compress/licenses/zstd-jni-NOTICE.txt
diff --git a/libs/compress/src/main/java/org/opensearch/compress/ZstdCompressor.java b/libs/compress/src/main/java/org/opensearch/compress/ZstdCompressor.java
new file mode 100644
index 0000000000000..e2a740f72be93
--- /dev/null
+++ b/libs/compress/src/main/java/org/opensearch/compress/ZstdCompressor.java
@@ -0,0 +1,136 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+package org.opensearch.compress;
+
+import com.github.luben.zstd.RecyclingBufferPool;
+import com.github.luben.zstd.ZstdInputStreamNoFinalizer;
+import com.github.luben.zstd.ZstdOutputStreamNoFinalizer;
+
+import org.opensearch.common.annotation.PublicApi;
+import org.opensearch.core.common.bytes.BytesReference;
+import org.opensearch.core.compress.Compressor;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+
+/**
+ * {@link Compressor} implementation based on the ZSTD compression algorithm.
+ *
+ * @opensearch.api - registered name requires BWC support
+ * @opensearch.experimental - class methods might change
+ */
+public class ZstdCompressor implements Compressor {
+
+ /**
+ * An arbitrary header that we use to identify compressed streams
+ * It needs to be different from other compressors and to not be specific
+ * enough so that no stream starting with these bytes could be detected as
+ * a XContent
+ * */
+ private static final byte[] HEADER = new byte[] { 'Z', 'S', 'T', 'D', '\0' };
+
+ /**
+ * The name to register the compressor by
+ *
+ * @opensearch.api - requires BWC support
+ */
+ @PublicApi(since = "2.10.0")
+ public static final String NAME = "ZSTD";
+
+ /**
+ * The compression level for {@link ZstdOutputStreamNoFinalizer}
+ */
+ private static final int LEVEL = 3;
+
+ /** The buffer size for {@link BufferedInputStream} and {@link BufferedOutputStream}
+ */
+ private static final int BUFFER_SIZE = 4096;
+
+ /**
+ * Compares the given bytes with the {@link ZstdCompressor#HEADER} of a compressed stream
+ * @param bytes the bytes to compare to ({@link ZstdCompressor#HEADER})
+ * @return true if the bytes are the {@link ZstdCompressor#HEADER}, false otherwise
+ */
+ @Override
+ public boolean isCompressed(BytesReference bytes) {
+ if (bytes.length() < HEADER.length) {
+ return false;
+ }
+ for (int i = 0; i < HEADER.length; ++i) {
+ if (bytes.get(i) != HEADER[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the length of the {@link ZstdCompressor#HEADER}
+ * @return the {@link ZstdCompressor#HEADER} length
+ */
+ @Override
+ public int headerLength() {
+ return HEADER.length;
+ }
+
+ /**
+ * Returns a new {@link ZstdInputStreamNoFinalizer} from the given compressed {@link InputStream}
+ * @param in the compressed {@link InputStream}
+ * @return a new {@link ZstdInputStreamNoFinalizer} from the given compressed {@link InputStream}
+ * @throws IOException if an I/O error occurs
+ * @throws IllegalArgumentException if the input stream is not compressed with ZSTD
+ */
+ @Override
+ public InputStream threadLocalInputStream(InputStream in) throws IOException {
+ final byte[] header = in.readNBytes(HEADER.length);
+ if (Arrays.equals(header, HEADER) == false) {
+ throw new IllegalArgumentException("Input stream is not compressed with ZSTD!");
+ }
+ return new ZstdInputStreamNoFinalizer(new BufferedInputStream(in, BUFFER_SIZE), RecyclingBufferPool.INSTANCE);
+ }
+
+ /**
+ * Returns a new {@link ZstdOutputStreamNoFinalizer} from the given {@link OutputStream}
+ * @param out the {@link OutputStream}
+ * @return a new {@link ZstdOutputStreamNoFinalizer} from the given {@link OutputStream}
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public OutputStream threadLocalOutputStream(OutputStream out) throws IOException {
+ out.write(HEADER);
+ return new ZstdOutputStreamNoFinalizer(new BufferedOutputStream(out, BUFFER_SIZE), RecyclingBufferPool.INSTANCE, LEVEL);
+ }
+
+ /**
+ * Always throws an {@link UnsupportedOperationException} as ZSTD compression is supported only for snapshotting
+ * @param bytesReference a reference to the bytes to uncompress
+ * @return always throws an exception
+ * @throws UnsupportedOperationException if the method is called
+ * @throws IOException is never thrown
+ */
+ @Override
+ public BytesReference uncompress(BytesReference bytesReference) throws IOException {
+ throw new UnsupportedOperationException("ZSTD compression is supported only for snapshotting");
+ }
+
+ /**
+ * Always throws an {@link UnsupportedOperationException} as ZSTD compression is supported only for snapshotting
+ * @param bytesReference a reference to the bytes to compress
+ * @return always throws an exception
+ * @throws UnsupportedOperationException if the method is called
+ */
+ @Override
+ public BytesReference compress(BytesReference bytesReference) throws IOException {
+ throw new UnsupportedOperationException("ZSTD compression is supported only for snapshotting");
+ }
+}
diff --git a/server/src/main/java/org/opensearch/index/codec/customcodecs/package-info.java b/libs/compress/src/main/java/org/opensearch/compress/package-info.java
similarity index 63%
rename from server/src/main/java/org/opensearch/index/codec/customcodecs/package-info.java
rename to libs/compress/src/main/java/org/opensearch/compress/package-info.java
index e996873963b1b..3ffa53079fa69 100644
--- a/server/src/main/java/org/opensearch/index/codec/customcodecs/package-info.java
+++ b/libs/compress/src/main/java/org/opensearch/compress/package-info.java
@@ -7,6 +7,6 @@
*/
/**
- * A plugin that implements compression codecs with native implementation.
+ * Concrete {@link org.opensearch.core.compress.Compressor} implementations
*/
-package org.opensearch.index.codec.customcodecs;
+package org.opensearch.compress;
diff --git a/libs/compress/src/main/java/org/opensearch/compress/spi/CompressionProvider.java b/libs/compress/src/main/java/org/opensearch/compress/spi/CompressionProvider.java
new file mode 100644
index 0000000000000..f0c6969377d78
--- /dev/null
+++ b/libs/compress/src/main/java/org/opensearch/compress/spi/CompressionProvider.java
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+package org.opensearch.compress.spi;
+
+import org.opensearch.compress.ZstdCompressor;
+import org.opensearch.core.compress.Compressor;
+import org.opensearch.core.compress.spi.CompressorProvider;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.List;
+import java.util.Map.Entry;
+
+/**
+ * Additional "optional" compressor implementations provided by the opensearch compress library
+ *
+ * @opensearch.internal
+ */
+public class CompressionProvider implements CompressorProvider {
+
+ /**
+ * Returns the concrete {@link Compressor}s provided by the compress library
+ * @return a list of {@link Compressor}s
+ * */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public List> getCompressors() {
+ return List.of(new SimpleEntry<>(ZstdCompressor.NAME, new ZstdCompressor()));
+ }
+}
diff --git a/libs/compress/src/main/java/org/opensearch/compress/spi/package-info.java b/libs/compress/src/main/java/org/opensearch/compress/spi/package-info.java
new file mode 100644
index 0000000000000..47d982a7ca2f9
--- /dev/null
+++ b/libs/compress/src/main/java/org/opensearch/compress/spi/package-info.java
@@ -0,0 +1,15 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+/**
+ * Service Provider Interface for registering concrete {@link org.opensearch.core.compress.Compressor}
+ * implementations.
+ *
+ * See {@link org.opensearch.compress.ZstdCompressor}
+ */
+package org.opensearch.compress.spi;
diff --git a/libs/compress/src/main/java/org/opensearch/package-info.java b/libs/compress/src/main/java/org/opensearch/package-info.java
new file mode 100644
index 0000000000000..264680e9cb271
--- /dev/null
+++ b/libs/compress/src/main/java/org/opensearch/package-info.java
@@ -0,0 +1,13 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+/**
+ * This is the compress library for registering optional
+ * {@link org.opensearch.core.compress.Compressor} implementations
+ */
+package org.opensearch;
diff --git a/libs/compress/src/main/resources/META-INF/services/org.opensearch.core.compress.spi.CompressorProvider b/libs/compress/src/main/resources/META-INF/services/org.opensearch.core.compress.spi.CompressorProvider
new file mode 100644
index 0000000000000..a9ea063e24436
--- /dev/null
+++ b/libs/compress/src/main/resources/META-INF/services/org.opensearch.core.compress.spi.CompressorProvider
@@ -0,0 +1,9 @@
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# The OpenSearch Contributors require contributions made to
+# this file be licensed under the Apache-2.0 license or a
+# compatible open source license.
+#
+
+org.opensearch.compress.spi.CompressionProvider
diff --git a/server/src/test/java/org/opensearch/common/compress/ZstdCompressTests.java b/libs/compress/src/test/java/org/opensearch/compress/ZstdCompressTests.java
similarity index 58%
rename from server/src/test/java/org/opensearch/common/compress/ZstdCompressTests.java
rename to libs/compress/src/test/java/org/opensearch/compress/ZstdCompressTests.java
index b8de4a4e4bb1b..54864054a0e02 100644
--- a/server/src/test/java/org/opensearch/common/compress/ZstdCompressTests.java
+++ b/libs/compress/src/test/java/org/opensearch/compress/ZstdCompressTests.java
@@ -6,17 +6,20 @@
* compatible open source license.
*/
-package org.opensearch.common.compress;
+package org.opensearch.compress;
+
+import org.opensearch.core.compress.Compressor;
+import org.opensearch.test.core.compress.AbstractCompressorTestCase;
/**
* Test streaming compression
*/
-public class ZstdCompressTests extends AbstractCompressorTests {
+public class ZstdCompressTests extends AbstractCompressorTestCase {
private final Compressor compressor = new ZstdCompressor();
@Override
- Compressor compressor() {
+ protected Compressor compressor() {
return compressor;
}
}
diff --git a/libs/core/licenses/lucene-core-9.7.0.jar.sha1 b/libs/core/licenses/lucene-core-9.7.0.jar.sha1
deleted file mode 100644
index 2b0f77275c0ab..0000000000000
--- a/libs/core/licenses/lucene-core-9.7.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ad391210ffd806931334be9670a35af00c56f959
\ No newline at end of file
diff --git a/libs/core/licenses/lucene-core-9.8.0-snapshot-95cdd2e.jar.sha1 b/libs/core/licenses/lucene-core-9.8.0-snapshot-95cdd2e.jar.sha1
new file mode 100644
index 0000000000000..70baf1270cd5d
--- /dev/null
+++ b/libs/core/licenses/lucene-core-9.8.0-snapshot-95cdd2e.jar.sha1
@@ -0,0 +1 @@
+d2f7fbc5b2c49ca777a169d579f41082a9a57cc7
\ No newline at end of file
diff --git a/libs/core/src/main/java/org/opensearch/ExceptionsHelper.java b/libs/core/src/main/java/org/opensearch/ExceptionsHelper.java
index a03b2f94b27fe..9692d20a050ff 100644
--- a/libs/core/src/main/java/org/opensearch/ExceptionsHelper.java
+++ b/libs/core/src/main/java/org/opensearch/ExceptionsHelper.java
@@ -33,16 +33,17 @@
package org.opensearch;
import com.fasterxml.jackson.core.JsonParseException;
+
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexFormatTooNewException;
import org.apache.lucene.index.IndexFormatTooOldException;
-import org.opensearch.core.action.ShardOperationFailedException;
import org.opensearch.common.CheckedRunnable;
import org.opensearch.common.CheckedSupplier;
import org.opensearch.common.Nullable;
-import org.opensearch.core.common.compress.NotXContentException;
+import org.opensearch.core.action.ShardOperationFailedException;
+import org.opensearch.core.compress.NotXContentException;
import org.opensearch.core.concurrency.OpenSearchRejectedExecutionException;
import org.opensearch.core.index.Index;
import org.opensearch.core.rest.RestStatus;
diff --git a/libs/core/src/main/java/org/opensearch/OpenSearchException.java b/libs/core/src/main/java/org/opensearch/OpenSearchException.java
index f75a225af1b4d..5bad711a15032 100644
--- a/libs/core/src/main/java/org/opensearch/OpenSearchException.java
+++ b/libs/core/src/main/java/org/opensearch/OpenSearchException.java
@@ -34,20 +34,20 @@
import org.opensearch.common.CheckedFunction;
import org.opensearch.common.Nullable;
import org.opensearch.common.collect.Tuple;
+import org.opensearch.core.ParseField;
+import org.opensearch.core.common.Strings;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.io.stream.StreamOutput;
import org.opensearch.core.common.io.stream.Writeable;
-import org.opensearch.core.ParseField;
-import org.opensearch.core.common.Strings;
import org.opensearch.core.common.logging.LoggerMessageFormat;
+import org.opensearch.core.index.Index;
+import org.opensearch.core.index.shard.ShardId;
+import org.opensearch.core.rest.RestStatus;
import org.opensearch.core.xcontent.ToXContent;
import org.opensearch.core.xcontent.ToXContentFragment;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.core.xcontent.XContentParseException;
import org.opensearch.core.xcontent.XContentParser;
-import org.opensearch.core.index.Index;
-import org.opensearch.core.index.shard.ShardId;
-import org.opensearch.core.rest.RestStatus;
import java.io.IOException;
import java.util.ArrayList;
@@ -61,12 +61,11 @@
import java.util.concurrent.ConcurrentHashMap;
import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonMap;
import static org.opensearch.OpenSearchException.OpenSearchExceptionHandleRegistry.registerExceptionHandle;
import static org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken;
import static org.opensearch.core.xcontent.XContentParserUtils.ensureFieldName;
-import static java.util.Collections.singletonMap;
-
/**
* A core library base class for all opensearch exceptions.
*
@@ -118,6 +117,14 @@ public class OpenSearchException extends RuntimeException implements Writeable,
UNKNOWN_VERSION_ADDED
)
);
+ registerExceptionHandle(
+ new OpenSearchExceptionHandle(
+ org.opensearch.OpenSearchParseException.class,
+ org.opensearch.OpenSearchParseException::new,
+ 35,
+ UNKNOWN_VERSION_ADDED
+ )
+ );
registerExceptionHandle(
new OpenSearchExceptionHandle(
org.opensearch.core.common.ParsingException.class,
@@ -134,6 +141,22 @@ public class OpenSearchException extends RuntimeException implements Writeable,
UNKNOWN_VERSION_ADDED
)
);
+ registerExceptionHandle(
+ new OpenSearchExceptionHandle(
+ org.opensearch.core.common.breaker.CircuitBreakingException.class,
+ org.opensearch.core.common.breaker.CircuitBreakingException::new,
+ 133,
+ UNKNOWN_VERSION_ADDED
+ )
+ );
+ registerExceptionHandle(
+ new OpenSearchExceptionHandle(
+ org.opensearch.core.tasks.TaskCancelledException.class,
+ org.opensearch.core.tasks.TaskCancelledException::new,
+ 146,
+ UNKNOWN_VERSION_ADDED
+ )
+ );
}
/**
diff --git a/server/src/main/java/org/opensearch/OpenSearchParseException.java b/libs/core/src/main/java/org/opensearch/OpenSearchParseException.java
similarity index 100%
rename from server/src/main/java/org/opensearch/OpenSearchParseException.java
rename to libs/core/src/main/java/org/opensearch/OpenSearchParseException.java
diff --git a/libs/core/src/main/java/org/opensearch/Version.java b/libs/core/src/main/java/org/opensearch/Version.java
index f85da63bdbb1f..32f4ca0317907 100644
--- a/libs/core/src/main/java/org/opensearch/Version.java
+++ b/libs/core/src/main/java/org/opensearch/Version.java
@@ -33,6 +33,7 @@
package org.opensearch;
import org.opensearch.common.SuppressForbidden;
+import org.opensearch.common.annotation.PublicApi;
import org.opensearch.core.xcontent.ToXContentFragment;
import org.opensearch.core.xcontent.XContentBuilder;
@@ -50,12 +51,13 @@
*
* @opensearch.api
*/
+@PublicApi(since = "1.0.0")
public class Version implements Comparable, ToXContentFragment {
/*
* The logic for ID is: XXYYZZAA, where XX is major version, YY is minor version, ZZ is revision, and AA is alpha/beta/rc indicator AA
* values below 25 are for alpha builder (since 5.0), and above 25 and below 50 are beta builds, and below 99 are RC builds, with 99
* indicating a release the (internal) format of the id is there so we can easily do after/before checks on the id
- *
+ *>>
* IMPORTANT: Unreleased vs. Released Versions
*
* All listed versions MUST be released versions, except the last major, the last minor and the last revison. ONLY those are required
@@ -90,8 +92,10 @@ public class Version implements Comparable, ToXContentFragment {
public static final Version V_2_8_0 = new Version(2080099, org.apache.lucene.util.Version.LUCENE_9_6_0);
public static final Version V_2_8_1 = new Version(2080199, org.apache.lucene.util.Version.LUCENE_9_6_0);
public static final Version V_2_9_0 = new Version(2090099, org.apache.lucene.util.Version.LUCENE_9_7_0);
+ public static final Version V_2_9_1 = new Version(2090199, org.apache.lucene.util.Version.LUCENE_9_7_0);
public static final Version V_2_10_0 = new Version(2100099, org.apache.lucene.util.Version.LUCENE_9_7_0);
- public static final Version V_3_0_0 = new Version(3000099, org.apache.lucene.util.Version.LUCENE_9_7_0);
+ public static final Version V_2_11_0 = new Version(2110099, org.apache.lucene.util.Version.LUCENE_9_7_0);
+ public static final Version V_3_0_0 = new Version(3000099, org.apache.lucene.util.Version.LUCENE_9_8_0);
public static final Version CURRENT = V_3_0_0;
public static Version fromId(int id) {
diff --git a/libs/core/src/main/java/org/opensearch/core/ParseField.java b/libs/core/src/main/java/org/opensearch/core/ParseField.java
index 5741f97d1d335..171b8eaf5c397 100644
--- a/libs/core/src/main/java/org/opensearch/core/ParseField.java
+++ b/libs/core/src/main/java/org/opensearch/core/ParseField.java
@@ -31,6 +31,7 @@
package org.opensearch.core;
+import org.opensearch.common.annotation.PublicApi;
import org.opensearch.core.xcontent.DeprecationHandler;
import org.opensearch.core.xcontent.XContentLocation;
@@ -43,7 +44,11 @@
/**
* Holds a field that can be found in a request while parsing and its different
* variants, which may be deprecated.
+ *
+ * @opensearch.api
+ *
*/
+@PublicApi(since = "1.0.0")
public class ParseField {
private final String name;
private final String[] deprecatedNames;
diff --git a/server/src/main/java/org/opensearch/action/ActionListener.java b/libs/core/src/main/java/org/opensearch/core/action/ActionListener.java
similarity index 99%
rename from server/src/main/java/org/opensearch/action/ActionListener.java
rename to libs/core/src/main/java/org/opensearch/core/action/ActionListener.java
index 645ed4deec006..119e56cfe0bf2 100644
--- a/server/src/main/java/org/opensearch/action/ActionListener.java
+++ b/libs/core/src/main/java/org/opensearch/core/action/ActionListener.java
@@ -30,13 +30,14 @@
* GitHub history for details.
*/
-package org.opensearch.action;
+package org.opensearch.core.action;
import org.opensearch.ExceptionsHelper;
import org.opensearch.common.CheckedConsumer;
import org.opensearch.common.CheckedFunction;
import org.opensearch.common.CheckedRunnable;
import org.opensearch.common.CheckedSupplier;
+import org.opensearch.common.annotation.PublicApi;
import java.util.ArrayList;
import java.util.List;
@@ -48,6 +49,7 @@
*
* @opensearch.api
*/
+@PublicApi(since = "1.0.0")
public interface ActionListener {
/**
* Handle action response. This response may constitute a failure or a
diff --git a/server/src/main/java/org/opensearch/action/ActionResponse.java b/libs/core/src/main/java/org/opensearch/core/action/ActionResponse.java
similarity index 94%
rename from server/src/main/java/org/opensearch/action/ActionResponse.java
rename to libs/core/src/main/java/org/opensearch/core/action/ActionResponse.java
index fd13971433d8b..041d8b1bffb4a 100644
--- a/server/src/main/java/org/opensearch/action/ActionResponse.java
+++ b/libs/core/src/main/java/org/opensearch/core/action/ActionResponse.java
@@ -30,10 +30,10 @@
* GitHub history for details.
*/
-package org.opensearch.action;
+package org.opensearch.core.action;
import org.opensearch.core.common.io.stream.StreamInput;
-import org.opensearch.transport.TransportResponse;
+import org.opensearch.core.transport.TransportResponse;
import java.io.IOException;
diff --git a/server/src/main/java/org/opensearch/action/NotifyOnceListener.java b/libs/core/src/main/java/org/opensearch/core/action/NotifyOnceListener.java
similarity index 98%
rename from server/src/main/java/org/opensearch/action/NotifyOnceListener.java
rename to libs/core/src/main/java/org/opensearch/core/action/NotifyOnceListener.java
index cc625962e54f6..6af9ca005d171 100644
--- a/server/src/main/java/org/opensearch/action/NotifyOnceListener.java
+++ b/libs/core/src/main/java/org/opensearch/core/action/NotifyOnceListener.java
@@ -30,7 +30,7 @@
* GitHub history for details.
*/
-package org.opensearch.action;
+package org.opensearch.core.action;
import java.util.concurrent.atomic.AtomicBoolean;
diff --git a/libs/core/src/main/java/org/opensearch/core/action/ShardOperationFailedException.java b/libs/core/src/main/java/org/opensearch/core/action/ShardOperationFailedException.java
index 9fdd4ae273a8b..7456dcd335f72 100644
--- a/libs/core/src/main/java/org/opensearch/core/action/ShardOperationFailedException.java
+++ b/libs/core/src/main/java/org/opensearch/core/action/ShardOperationFailedException.java
@@ -34,8 +34,8 @@
import org.opensearch.common.Nullable;
import org.opensearch.core.common.io.stream.Writeable;
-import org.opensearch.core.xcontent.ToXContentObject;
import org.opensearch.core.rest.RestStatus;
+import org.opensearch.core.xcontent.ToXContentObject;
import java.util.Objects;
diff --git a/libs/core/src/main/java/org/opensearch/core/action/support/DefaultShardOperationFailedException.java b/libs/core/src/main/java/org/opensearch/core/action/support/DefaultShardOperationFailedException.java
index ccb35ad5c6c6f..777f8d04758d0 100644
--- a/libs/core/src/main/java/org/opensearch/core/action/support/DefaultShardOperationFailedException.java
+++ b/libs/core/src/main/java/org/opensearch/core/action/support/DefaultShardOperationFailedException.java
@@ -34,15 +34,15 @@
import org.opensearch.ExceptionsHelper;
import org.opensearch.OpenSearchException;
-import org.opensearch.core.action.ShardOperationFailedException;
import org.opensearch.core.ParseField;
+import org.opensearch.core.action.ShardOperationFailedException;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.io.stream.StreamOutput;
import org.opensearch.core.common.io.stream.Writeable;
+import org.opensearch.core.rest.RestStatus;
import org.opensearch.core.xcontent.ConstructingObjectParser;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.core.xcontent.XContentParser;
-import org.opensearch.core.rest.RestStatus;
import java.io.IOException;
diff --git a/libs/core/src/main/java/org/opensearch/core/common/ParsingException.java b/libs/core/src/main/java/org/opensearch/core/common/ParsingException.java
index d2cd7a3170792..b6dc7dc928b3e 100644
--- a/libs/core/src/main/java/org/opensearch/core/common/ParsingException.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/ParsingException.java
@@ -35,10 +35,10 @@
import org.opensearch.OpenSearchException;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.io.stream.StreamOutput;
+import org.opensearch.core.rest.RestStatus;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.core.xcontent.XContentLocation;
import org.opensearch.core.xcontent.XContentParser;
-import org.opensearch.core.rest.RestStatus;
import java.io.IOException;
diff --git a/libs/core/src/main/java/org/opensearch/core/common/Strings.java b/libs/core/src/main/java/org/opensearch/core/common/Strings.java
index d6c484e5e4746..6227716af9cc9 100644
--- a/libs/core/src/main/java/org/opensearch/core/common/Strings.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/Strings.java
@@ -8,9 +8,18 @@
package org.opensearch.core.common;
+import org.apache.lucene.util.BytesRefBuilder;
+import org.opensearch.ExceptionsHelper;
+import org.opensearch.OpenSearchException;
import org.opensearch.common.Nullable;
+import org.opensearch.core.common.bytes.BytesReference;
+import org.opensearch.core.common.util.CollectionUtils;
+import org.opensearch.core.xcontent.MediaType;
+import org.opensearch.core.xcontent.ToXContent;
+import org.opensearch.core.xcontent.XContentBuilder;
import java.io.BufferedReader;
+import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
@@ -24,6 +33,9 @@
import java.util.TreeSet;
import java.util.function.Supplier;
+import static java.util.Collections.unmodifiableSet;
+import static org.opensearch.common.util.set.Sets.newHashSet;
+
/**
* String utility class.
*
@@ -34,115 +46,29 @@
public class Strings {
public static final String UNKNOWN_UUID_VALUE = "_na_";
public static final String[] EMPTY_ARRAY = new String[0];
+ public static final Set INVALID_FILENAME_CHARS = unmodifiableSet(
+ newHashSet('\\', '/', '*', '?', '"', '<', '>', '|', ' ', ',')
+ );
- /**
- * Split the specified string by commas to an array.
- *
- * @param s the string to split
- * @return the array of split values
- * @see String#split(String)
- */
- public static String[] splitStringByCommaToArray(final String s) {
- if (s == null || s.isEmpty()) return Strings.EMPTY_ARRAY;
- else return s.split(",");
- }
-
- /**
- * Convenience method to return a Collection as a delimited (e.g. CSV)
- * String. E.g. useful for toString()
implementations.
- *
- * @param coll the Collection to display
- * @param delim the delimiter to use (probably a ",")
- * @param prefix the String to start each element with
- * @param suffix the String to end each element with
- * @return the delimited String
- */
- public static String collectionToDelimitedString(Iterable> coll, String delim, String prefix, String suffix) {
- StringBuilder sb = new StringBuilder();
- collectionToDelimitedString(coll, delim, prefix, suffix, sb);
- return sb.toString();
- }
-
- public static void collectionToDelimitedString(Iterable> coll, String delim, String prefix, String suffix, StringBuilder sb) {
- Iterator> it = coll.iterator();
- while (it.hasNext()) {
- sb.append(prefix).append(it.next()).append(suffix);
- if (it.hasNext()) {
- sb.append(delim);
- }
- }
- }
-
- /**
- * Convenience method to return a Collection as a delimited (e.g. CSV)
- * String. E.g. useful for toString()
implementations.
- *
- * @param coll the Collection to display
- * @param delim the delimiter to use (probably a ",")
- * @return the delimited String
- */
- public static String collectionToDelimitedString(Iterable> coll, String delim) {
- return collectionToDelimitedString(coll, delim, "", "");
- }
-
- /**
- * Convenience method to return a Collection as a CSV String.
- * E.g. useful for toString()
implementations.
- *
- * @param coll the Collection to display
- * @return the delimited String
- */
- public static String collectionToCommaDelimitedString(Iterable> coll) {
- return collectionToDelimitedString(coll, ",");
- }
+ // no instance:
+ private Strings() {}
- /**
- * Convenience method to return a String array as a delimited (e.g. CSV)
- * String. E.g. useful for toString()
implementations.
- *
- * @param arr the array to display
- * @param delim the delimiter to use (probably a ",")
- * @return the delimited String
- */
- public static String arrayToDelimitedString(Object[] arr, String delim) {
- StringBuilder sb = new StringBuilder();
- arrayToDelimitedString(arr, delim, sb);
- return sb.toString();
- }
+ // ---------------------------------------------------------------------
+ // General convenience methods for working with Strings
+ // ---------------------------------------------------------------------
- public static void arrayToDelimitedString(Object[] arr, String delim, StringBuilder sb) {
- if (isEmpty(arr)) {
- return;
- }
- for (int i = 0; i < arr.length; i++) {
- if (i > 0) {
- sb.append(delim);
+ public static void spaceify(int spaces, String from, StringBuilder to) throws Exception {
+ try (BufferedReader reader = new BufferedReader(new StringReader(from))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ for (int i = 0; i < spaces; i++) {
+ to.append(' ');
+ }
+ to.append(line).append('\n');
}
- sb.append(arr[i]);
}
}
- /**
- * Convenience method to return a String array as a CSV String.
- * E.g. useful for toString()
implementations.
- *
- * @param arr the array to display
- * @return the delimited String
- */
- public static String arrayToCommaDelimitedString(Object[] arr) {
- return arrayToDelimitedString(arr, ",");
- }
-
- /**
- * Determine whether the given array is empty:
- * i.e. null
or of zero length.
- *
- * @param array the array to check
- */
- private static boolean isEmpty(Object[] array) {
- return (array == null || array.length == 0);
- }
-
/**
* Check that the given CharSequence is neither null
nor of length 0.
* Note: Will return true
for a CharSequence that purely consists of whitespace.
@@ -161,6 +87,18 @@ public static boolean hasLength(CharSequence str) {
return (str != null && str.length() > 0);
}
+ /**
+ * Check that the given BytesReference is neither null
nor of length 0
+ * Note: Will return true
for a BytesReference that purely consists of whitespace.
+ *
+ * @param bytesReference the BytesReference to check (may be null
)
+ * @return true
if the BytesReference is not null and has length
+ * @see Strings#hasLength(CharSequence)
+ */
+ public static boolean hasLength(final BytesReference bytesReference) {
+ return (bytesReference != null && bytesReference.length() > 0);
+ }
+
/**
* Check that the given String is neither null
nor of length 0.
* Note: Will return true
for a String that purely consists of whitespace.
@@ -169,7 +107,7 @@ public static boolean hasLength(CharSequence str) {
* @return true
if the String is not null and has length
* @see Strings#hasLength(CharSequence)
*/
- public static boolean hasLength(String str) {
+ public static boolean hasLength(final String str) {
return hasLength((CharSequence) str);
}
@@ -186,7 +124,7 @@ public static boolean hasLength(String str) {
* @param str the CharSequence to check (may be null
)
* @return true
if the CharSequence is either null or has a zero length
*/
- public static boolean isEmpty(CharSequence str) {
+ public static boolean isEmpty(final CharSequence str) {
return hasLength(str) == false;
}
@@ -234,6 +172,42 @@ public static boolean hasText(String str) {
return hasText((CharSequence) str);
}
+ /**
+ * Trim all occurrences of the supplied leading character from the given String.
+ *
+ * @param str the String to check
+ * @param leadingCharacter the leading character to be trimmed
+ * @return the trimmed String
+ */
+ public static String trimLeadingCharacter(String str, char leadingCharacter) {
+ if (hasLength(str) == false) {
+ return str;
+ }
+ StringBuilder sb = new StringBuilder(str);
+ while (sb.length() > 0 && sb.charAt(0) == leadingCharacter) {
+ sb.deleteCharAt(0);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Test whether the given string matches the given substring
+ * at the given index.
+ *
+ * @param str the original string (or StringBuilder)
+ * @param index the index in the original string to start matching against
+ * @param substring the substring to match at the given index
+ */
+ public static boolean substringMatch(CharSequence str, int index, CharSequence substring) {
+ for (int j = 0; j < substring.length(); j++) {
+ int i = index + j;
+ if (i >= str.length() || str.charAt(i) != substring.charAt(j)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* Replace all occurrences of a substring within a string with
* another string.
@@ -263,24 +237,6 @@ public static String replace(String inString, String oldPattern, String newPatte
return sb.toString();
}
- /**
- * Trim all occurrences of the supplied leading character from the given String.
- *
- * @param str the String to check
- * @param leadingCharacter the leading character to be trimmed
- * @return the trimmed String
- */
- public static String trimLeadingCharacter(String str, char leadingCharacter) {
- if (hasLength(str) == false) {
- return str;
- }
- StringBuilder sb = new StringBuilder(str);
- while (sb.length() > 0 && sb.charAt(0) == leadingCharacter) {
- sb.deleteCharAt(0);
- }
- return sb.toString();
- }
-
/**
* Delete all occurrences of the given substring.
*
@@ -314,16 +270,65 @@ public static String deleteAny(String inString, String charsToDelete) {
return sb.toString();
}
- public static void spaceify(int spaces, String from, StringBuilder to) throws Exception {
- try (BufferedReader reader = new BufferedReader(new StringReader(from))) {
- String line;
- while ((line = reader.readLine()) != null) {
- for (int i = 0; i < spaces; i++) {
- to.append(' ');
- }
- to.append(line).append('\n');
+ // ---------------------------------------------------------------------
+ // Convenience methods for working with formatted Strings
+ // ---------------------------------------------------------------------
+
+ /**
+ * Quote the given String with single quotes.
+ *
+ * @param str the input String (e.g. "myString")
+ * @return the quoted String (e.g. "'myString'"),
+ * or null
if the input was null
+ */
+ public static String quote(String str) {
+ return (str != null ? "'" + str + "'" : null);
+ }
+
+ /**
+ * Capitalize a String
, changing the first letter to
+ * upper case as per {@link Character#toUpperCase(char)}.
+ * No other letters are changed.
+ *
+ * @param str the String to capitalize, may be null
+ * @return the capitalized String, null
if null
+ */
+ public static String capitalize(String str) {
+ return changeFirstCharacterCase(str, true);
+ }
+
+ private static String changeFirstCharacterCase(String str, boolean capitalize) {
+ if (str == null || str.length() == 0) {
+ return str;
+ }
+ StringBuilder sb = new StringBuilder(str.length());
+ if (capitalize) {
+ sb.append(Character.toUpperCase(str.charAt(0)));
+ } else {
+ sb.append(Character.toLowerCase(str.charAt(0)));
+ }
+ sb.append(str.substring(1));
+ return sb.toString();
+ }
+
+ public static boolean validFileName(String fileName) {
+ for (int i = 0; i < fileName.length(); i++) {
+ char c = fileName.charAt(i);
+ if (INVALID_FILENAME_CHARS.contains(c)) {
+ return false;
}
}
+ return true;
+ }
+
+ public static boolean validFileNameExcludingAstrix(String fileName) {
+ for (int i = 0; i < fileName.length(); i++) {
+ char c = fileName.charAt(i);
+ if (c != '*' && INVALID_FILENAME_CHARS.contains(c)) {
+ return false;
+ }
+ }
+ return true;
}
/**
@@ -341,47 +346,6 @@ public static String[] toStringArray(final Collection collection) {
return collection.toArray(new String[0]);
}
- /**
- * Take a String which is a delimited list and convert it to a String array.
- * A single delimiter can consists of more than one character: It will still
- * be considered as single delimiter string, rather than as bunch of potential
- * delimiter characters - in contrast to tokenizeToStringArray
.
- *
- * @param str the input String
- * @param delimiter the delimiter between elements (this is a single delimiter,
- * rather than a bunch individual delimiter characters)
- * @param charsToDelete a set of characters to delete. Useful for deleting unwanted
- * line breaks: e.g. "\r\n\f" will delete all new lines and line feeds in a String.
- * @return an array of the tokens in the list
- * @see #tokenizeToStringArray
- */
- public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {
- if (str == null) {
- return Strings.EMPTY_ARRAY;
- }
- if (delimiter == null) {
- return new String[] { str };
- }
- List result = new ArrayList<>();
- if ("".equals(delimiter)) {
- for (int i = 0; i < str.length(); i++) {
- result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
- }
- } else {
- int pos = 0;
- int delPos;
- while ((delPos = str.indexOf(delimiter, pos)) != -1) {
- result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
- pos = delPos + delimiter.length();
- }
- if (str.length() > 0 && pos <= str.length()) {
- // Add rest of String, but not in case of empty input.
- result.add(deleteAny(str.substring(pos), charsToDelete));
- }
- }
- return toStringArray(result);
- }
-
/**
* Tokenize the specified string by commas to a set, trimming whitespace and ignoring empty tokens.
*
@@ -393,6 +357,41 @@ public static Set tokenizeByCommaToSet(final String s) {
return tokenizeToCollection(s, ",", HashSet::new);
}
+ /**
+ * Split the specified string by commas to an array.
+ *
+ * @param s the string to split
+ * @return the array of split values
+ * @see String#split(String)
+ */
+ public static String[] splitStringByCommaToArray(final String s) {
+ if (s == null || s.isEmpty()) return Strings.EMPTY_ARRAY;
+ else return s.split(",");
+ }
+
+ /**
+ * Split a String at the first occurrence of the delimiter.
+ * Does not include the delimiter in the result.
+ *
+ * @param toSplit the string to split
+ * @param delimiter to split the string up with
+ * @return a two element array with index 0 being before the delimiter, and
+ * index 1 being after the delimiter (neither element includes the delimiter);
+ * or null
if the delimiter wasn't found in the given input String
+ */
+ public static String[] split(String toSplit, String delimiter) {
+ if (hasLength(toSplit) == false || hasLength(delimiter) == false) {
+ return null;
+ }
+ int offset = toSplit.indexOf(delimiter);
+ if (offset < 0) {
+ return null;
+ }
+ String beforeDelimiter = toSplit.substring(0, offset);
+ String afterDelimiter = toSplit.substring(offset + delimiter.length());
+ return new String[] { beforeDelimiter, afterDelimiter };
+ }
+
/**
* Tokenize the given String into a String array via a StringTokenizer.
* Trims tokens and omits empty tokens.
@@ -446,6 +445,47 @@ private static > T tokenizeToCollection(
return tokens;
}
+ /**
+ * Take a String which is a delimited list and convert it to a String array.
+ * A single delimiter can consists of more than one character: It will still
+ * be considered as single delimiter string, rather than as bunch of potential
+ * delimiter characters - in contrast to tokenizeToStringArray
.
+ *
+ * @param str the input String
+ * @param delimiter the delimiter between elements (this is a single delimiter,
+ * rather than a bunch individual delimiter characters)
+ * @param charsToDelete a set of characters to delete. Useful for deleting unwanted
+ * line breaks: e.g. "\r\n\f" will delete all new lines and line feeds in a String.
+ * @return an array of the tokens in the list
+ * @see #tokenizeToStringArray
+ */
+ public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {
+ if (str == null) {
+ return Strings.EMPTY_ARRAY;
+ }
+ if (delimiter == null) {
+ return new String[] { str };
+ }
+ List result = new ArrayList<>();
+ if ("".equals(delimiter)) {
+ for (int i = 0; i < str.length(); i++) {
+ result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
+ }
+ } else {
+ int pos = 0;
+ int delPos;
+ while ((delPos = str.indexOf(delimiter, pos)) != -1) {
+ result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
+ pos = delPos + delimiter.length();
+ }
+ if (str.length() > 0 && pos <= str.length()) {
+ // Add rest of String, but not in case of empty input.
+ result.add(deleteAny(str.substring(pos), charsToDelete));
+ }
+ }
+ return toStringArray(result);
+ }
+
/**
* Take a String which is a delimited list and convert it to a String array.
* A single delimiter can consists of more than one character: It will still
@@ -486,33 +526,293 @@ public static Set commaDelimitedListToSet(String str) {
return set;
}
- public static boolean isNullOrEmpty(@Nullable String s) {
- return s == null || s.isEmpty();
+ /**
+ * Convenience method to return a Collection as a delimited (e.g. CSV)
+ * String. E.g. useful for toString()
implementations.
+ *
+ * @param coll the Collection to display
+ * @param delim the delimiter to use (probably a ",")
+ * @param prefix the String to start each element with
+ * @param suffix the String to end each element with
+ * @return the delimited String
+ */
+ public static String collectionToDelimitedString(Iterable> coll, String delim, String prefix, String suffix) {
+ StringBuilder sb = new StringBuilder();
+ collectionToDelimitedString(coll, delim, prefix, suffix, sb);
+ return sb.toString();
+ }
+
+ public static void collectionToDelimitedString(Iterable> coll, String delim, String prefix, String suffix, StringBuilder sb) {
+ Iterator> it = coll.iterator();
+ while (it.hasNext()) {
+ sb.append(prefix).append(it.next()).append(suffix);
+ if (it.hasNext()) {
+ sb.append(delim);
+ }
+ }
}
/**
- * Capitalize a String
, changing the first letter to
- * upper case as per {@link Character#toUpperCase(char)}.
- * No other letters are changed.
+ * Convenience method to return a Collection as a delimited (e.g. CSV)
+ * String. E.g. useful for toString()
implementations.
*
- * @param str the String to capitalize, may be null
- * @return the capitalized String, null
if null
+ * @param coll the Collection to display
+ * @param delim the delimiter to use (probably a ",")
+ * @return the delimited String
*/
- public static String capitalize(String str) {
- return changeFirstCharacterCase(str, true);
+ public static String collectionToDelimitedString(Iterable> coll, String delim) {
+ return collectionToDelimitedString(coll, delim, "", "");
}
- private static String changeFirstCharacterCase(String str, boolean capitalize) {
- if (str == null || str.length() == 0) {
- return str;
+ /**
+ * Convenience method to return a Collection as a CSV String.
+ * E.g. useful for toString()
implementations.
+ *
+ * @param coll the Collection to display
+ * @return the delimited String
+ */
+ public static String collectionToCommaDelimitedString(Iterable> coll) {
+ return collectionToDelimitedString(coll, ",");
+ }
+
+ /**
+ * Convenience method to return a String array as a delimited (e.g. CSV)
+ * String. E.g. useful for toString()
implementations.
+ *
+ * @param arr the array to display
+ * @param delim the delimiter to use (probably a ",")
+ * @return the delimited String
+ */
+ public static String arrayToDelimitedString(Object[] arr, String delim) {
+ StringBuilder sb = new StringBuilder();
+ arrayToDelimitedString(arr, delim, sb);
+ return sb.toString();
+ }
+
+ public static void arrayToDelimitedString(Object[] arr, String delim, StringBuilder sb) {
+ if (isEmpty(arr)) {
+ return;
}
- StringBuilder sb = new StringBuilder(str.length());
- if (capitalize) {
- sb.append(Character.toUpperCase(str.charAt(0)));
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) {
+ sb.append(delim);
+ }
+ sb.append(arr[i]);
+ }
+ }
+
+ /**
+ * Convenience method to return a String array as a CSV String.
+ * E.g. useful for toString()
implementations.
+ *
+ * @param arr the array to display
+ * @return the delimited String
+ */
+ public static String arrayToCommaDelimitedString(Object[] arr) {
+ return arrayToDelimitedString(arr, ",");
+ }
+
+ /**
+ * Format the double value with a single decimal points, trimming trailing '.0'.
+ */
+ public static String format1Decimals(double value, String suffix) {
+ String p = String.valueOf(value);
+ int ix = p.indexOf('.') + 1;
+ int ex = p.indexOf('E');
+ char fraction = p.charAt(ix);
+ if (fraction == '0') {
+ if (ex != -1) {
+ return p.substring(0, ix - 1) + p.substring(ex) + suffix;
+ } else {
+ return p.substring(0, ix - 1) + suffix;
+ }
} else {
- sb.append(Character.toLowerCase(str.charAt(0)));
+ if (ex != -1) {
+ return p.substring(0, ix) + fraction + p.substring(ex) + suffix;
+ } else {
+ return p.substring(0, ix) + fraction + suffix;
+ }
}
- sb.append(str.substring(1));
- return sb.toString();
+ }
+
+ /**
+ * Determine whether the given array is empty:
+ * i.e. null
or of zero length.
+ *
+ * @param array the array to check
+ */
+ private static boolean isEmpty(final Object[] array) {
+ return (array == null || array.length == 0);
+ }
+
+ public static byte[] toUTF8Bytes(CharSequence charSequence) {
+ return toUTF8Bytes(charSequence, new BytesRefBuilder());
+ }
+
+ public static byte[] toUTF8Bytes(CharSequence charSequence, BytesRefBuilder spare) {
+ spare.copyChars(charSequence);
+ return Arrays.copyOf(spare.bytes(), spare.length());
+ }
+
+ /**
+ * Return substring(beginIndex, endIndex) that is impervious to string length.
+ */
+ public static String substring(String s, int beginIndex, int endIndex) {
+ if (s == null) {
+ return s;
+ }
+
+ int realEndIndex = s.length() > 0 ? s.length() - 1 : 0;
+
+ if (endIndex > realEndIndex) {
+ return s.substring(beginIndex);
+ } else {
+ return s.substring(beginIndex, endIndex);
+ }
+ }
+
+ /**
+ * If an array only consists of zero or one element, which is "*" or "_all" return an empty array
+ * which is usually used as everything
+ */
+ public static boolean isAllOrWildcard(String[] data) {
+ return CollectionUtils.isEmpty(data) || data.length == 1 && isAllOrWildcard(data[0]);
+ }
+
+ /**
+ * Returns `true` if the string is `_all` or `*`.
+ */
+ public static boolean isAllOrWildcard(String data) {
+ return "_all".equals(data) || "*".equals(data);
+ }
+
+ /**
+ * Return a {@link String} that is the json representation of the provided {@link ToXContent}.
+ * Wraps the output into an anonymous object if needed. The content is not pretty-printed
+ * nor human readable.
+ */
+ public static String toString(MediaType mediaType, ToXContent toXContent) {
+ return toString(mediaType, toXContent, false, false);
+ }
+
+ /**
+ * Return a {@link String} that is the json representation of the provided {@link ToXContent}.
+ * Wraps the output into an anonymous object if needed.
+ * Allows to configure the params.
+ * The content is not pretty-printed nor human readable.
+ */
+ public static String toString(MediaType mediaType, ToXContent toXContent, ToXContent.Params params) {
+ return toString(mediaType, toXContent, params, false, false);
+ }
+
+ /**
+ * Return a {@link String} that is the json representation of the provided {@link ToXContent}.
+ * Wraps the output into an anonymous object if needed. Allows to control whether the outputted
+ * json needs to be pretty printed and human readable.
+ *
+ */
+ public static String toString(MediaType mediaType, ToXContent toXContent, boolean pretty, boolean human) {
+ return toString(mediaType, toXContent, ToXContent.EMPTY_PARAMS, pretty, human);
+ }
+
+ /**
+ * Return a {@link String} that is the json representation of the provided {@link ToXContent}.
+ * Wraps the output into an anonymous object if needed.
+ * Allows to configure the params.
+ * Allows to control whether the outputted json needs to be pretty printed and human readable.
+ */
+ private static String toString(MediaType mediaType, ToXContent toXContent, ToXContent.Params params, boolean pretty, boolean human) {
+ try {
+ XContentBuilder builder = createBuilder(mediaType, pretty, human);
+ if (toXContent.isFragment()) {
+ builder.startObject();
+ }
+ toXContent.toXContent(builder, params);
+ if (toXContent.isFragment()) {
+ builder.endObject();
+ }
+ return builder.toString();
+ } catch (IOException e) {
+ try {
+ XContentBuilder builder = createBuilder(mediaType, pretty, human);
+ builder.startObject();
+ builder.field("error", "error building toString out of XContent: " + e.getMessage());
+ builder.field("stack_trace", ExceptionsHelper.stackTrace(e));
+ builder.endObject();
+ return builder.toString();
+ } catch (IOException e2) {
+ throw new OpenSearchException("cannot generate error message for deserialization", e);
+ }
+ }
+ }
+
+ private static XContentBuilder createBuilder(MediaType mediaType, boolean pretty, boolean human) throws IOException {
+ XContentBuilder builder = XContentBuilder.builder(mediaType.xContent());
+ if (pretty) {
+ builder.prettyPrint();
+ }
+ if (human) {
+ builder.humanReadable(true);
+ }
+ return builder;
+ }
+
+ /**
+ * Truncates string to a length less than length. Backtracks to throw out
+ * high surrogates.
+ */
+ public static String cleanTruncate(String s, int length) {
+ if (s == null) {
+ return s;
+ }
+ /*
+ * Its pretty silly for you to truncate to 0 length but just in case
+ * someone does this shouldn't break.
+ */
+ if (length == 0) {
+ return "";
+ }
+ if (length >= s.length()) {
+ return s;
+ }
+ if (Character.isHighSurrogate(s.charAt(length - 1))) {
+ length--;
+ }
+ return s.substring(0, length);
+ }
+
+ public static boolean isNullOrEmpty(@Nullable String s) {
+ return s == null || s.isEmpty();
+ }
+
+ public static String padStart(String s, int minimumLength, char c) {
+ if (s == null) {
+ throw new NullPointerException("s");
+ }
+ if (s.length() >= minimumLength) {
+ return s;
+ } else {
+ StringBuilder sb = new StringBuilder(minimumLength);
+ for (int i = s.length(); i < minimumLength; i++) {
+ sb.append(c);
+ }
+
+ sb.append(s);
+ return sb.toString();
+ }
+ }
+
+ public static String toLowercaseAscii(String in) {
+ StringBuilder out = new StringBuilder();
+ Iterator iter = in.codePoints().iterator();
+ while (iter.hasNext()) {
+ int codepoint = iter.next();
+ if (codepoint > 128) {
+ out.appendCodePoint(codepoint);
+ } else {
+ out.appendCodePoint(Character.toLowerCase(codepoint));
+ }
+ }
+ return out.toString();
}
}
diff --git a/server/src/main/java/org/opensearch/common/breaker/CircuitBreaker.java b/libs/core/src/main/java/org/opensearch/core/common/breaker/CircuitBreaker.java
similarity index 79%
rename from server/src/main/java/org/opensearch/common/breaker/CircuitBreaker.java
rename to libs/core/src/main/java/org/opensearch/core/common/breaker/CircuitBreaker.java
index 4cbd375e8c1ff..846950ff17c63 100644
--- a/server/src/main/java/org/opensearch/common/breaker/CircuitBreaker.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/breaker/CircuitBreaker.java
@@ -30,7 +30,7 @@
* GitHub history for details.
*/
-package org.opensearch.common.breaker;
+package org.opensearch.core.common.breaker;
import java.util.Locale;
@@ -71,17 +71,23 @@ public interface CircuitBreaker {
/**
* The type of breaker
- *
+ * can be {@link #MEMORY}, {@link #PARENT}, or {@link #NOOP}
* @opensearch.internal
*/
enum Type {
- // A regular or ChildMemoryCircuitBreaker
+ /** A regular or ChildMemoryCircuitBreaker */
MEMORY,
- // A special parent-type for the hierarchy breaker service
+ /** A special parent-type for the hierarchy breaker service */
PARENT,
- // A breaker where every action is a noop, it never breaks
+ /** A breaker where every action is a noop, it never breaks */
NOOP;
+ /**
+ * Converts string (case-insensitive) to breaker {@link Type}
+ * @param value "noop", "parent", or "memory" (case-insensitive)
+ * @return the breaker {@link Type}
+ * @throws IllegalArgumentException if value is not "noop", "parent", or "memory"
+ */
public static Type parseValue(String value) {
switch (value.toLowerCase(Locale.ROOT)) {
case "noop":
@@ -98,13 +104,13 @@ public static Type parseValue(String value) {
/**
* The breaker durability
- *
+ * can be {@link #TRANSIENT} or {@link #PERMANENT}
* @opensearch.internal
*/
enum Durability {
- // The condition that tripped the circuit breaker fixes itself eventually.
+ /** The condition that tripped the circuit breaker fixes itself eventually. */
TRANSIENT,
- // The condition that tripped the circuit breaker requires manual intervention.
+ /** The condition that tripped the circuit breaker requires manual intervention. */
PERMANENT
}
@@ -120,11 +126,14 @@ enum Durability {
* @param bytes number of bytes to add
* @param label string label describing the bytes being added
* @return the number of "used" bytes for the circuit breaker
+ * @throws CircuitBreakingException if the breaker tripped
*/
double addEstimateBytesAndMaybeBreak(long bytes, String label) throws CircuitBreakingException;
/**
* Adjust the circuit breaker without tripping
+ * @param bytes number of bytes to add
+ * @return the number of "used" bytes for the circuit breaker
*/
long addWithoutBreaking(long bytes);
@@ -154,7 +163,10 @@ enum Durability {
String getName();
/**
- * @return whether a tripped circuit breaker will reset itself (transient) or requires manual intervention (permanent).
+ * Returns the {@link Durability} of this breaker
+ * @return whether a tripped circuit breaker will
+ * reset itself ({@link Durability#TRANSIENT})
+ * or requires manual intervention ({@link Durability#PERMANENT}).
*/
Durability getDurability();
diff --git a/server/src/main/java/org/opensearch/common/breaker/CircuitBreakingException.java b/libs/core/src/main/java/org/opensearch/core/common/breaker/CircuitBreakingException.java
similarity index 92%
rename from server/src/main/java/org/opensearch/common/breaker/CircuitBreakingException.java
rename to libs/core/src/main/java/org/opensearch/core/common/breaker/CircuitBreakingException.java
index 4cab014912970..2df116dcad076 100644
--- a/server/src/main/java/org/opensearch/common/breaker/CircuitBreakingException.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/breaker/CircuitBreakingException.java
@@ -29,13 +29,13 @@
* GitHub history for details.
*/
-package org.opensearch.common.breaker;
+package org.opensearch.core.common.breaker;
import org.opensearch.OpenSearchException;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.io.stream.StreamOutput;
-import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.core.rest.RestStatus;
+import org.opensearch.core.xcontent.XContentBuilder;
import java.io.IOException;
@@ -46,8 +46,11 @@
*/
public class CircuitBreakingException extends OpenSearchException {
+ /** The number of bytes wanted */
private final long bytesWanted;
+ /** The circuit breaker limit */
private final long byteLimit;
+ /** The {@link CircuitBreaker.Durability} of the circuit breaker */
private final CircuitBreaker.Durability durability;
public CircuitBreakingException(StreamInput in) throws IOException {
@@ -88,6 +91,7 @@ public CircuitBreaker.Durability getDurability() {
return durability;
}
+ /** Always returns {@link RestStatus#TOO_MANY_REQUESTS} */
@Override
public RestStatus status() {
return RestStatus.TOO_MANY_REQUESTS;
diff --git a/server/src/main/java/org/opensearch/common/breaker/NoopCircuitBreaker.java b/libs/core/src/main/java/org/opensearch/core/common/breaker/NoopCircuitBreaker.java
similarity index 54%
rename from server/src/main/java/org/opensearch/common/breaker/NoopCircuitBreaker.java
rename to libs/core/src/main/java/org/opensearch/core/common/breaker/NoopCircuitBreaker.java
index ddd72280faa4f..17b9fefd27c99 100644
--- a/server/src/main/java/org/opensearch/common/breaker/NoopCircuitBreaker.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/breaker/NoopCircuitBreaker.java
@@ -30,68 +30,123 @@
* GitHub history for details.
*/
-package org.opensearch.common.breaker;
+package org.opensearch.core.common.breaker;
/**
- * A CircuitBreaker that doesn't increment or adjust, and all operations are
- * basically noops
- *
+ * A {@link CircuitBreaker} that doesn't increment or adjust, and all operations are
+ * basically noops.
+ * It never trips, limit is always -1, always returns 0 for all metrics.
* @opensearch.internal
*/
public class NoopCircuitBreaker implements CircuitBreaker {
- public static final int LIMIT = -1;
+ /** The limit of this breaker is always -1 */
+ public static final int LIMIT = -1;
+ /** Name of this breaker */
private final String name;
+ /**
+ * Creates a new NoopCircuitBreaker (that never trip) with the given name
+ * @param name the name of this breaker
+ */
public NoopCircuitBreaker(String name) {
this.name = name;
}
+ /**
+ * This is a noop, a noop breaker never trip
+ * @param fieldName name of this noop breaker
+ * @param bytesNeeded bytes needed
+ */
@Override
public void circuitBreak(String fieldName, long bytesNeeded) {
// noop
}
+ /**
+ * This is a noop, always return 0 and never throw/trip
+ * @param bytes number of bytes to add
+ * @param label string label describing the bytes being added
+ * @return always return 0
+ * @throws CircuitBreakingException never thrown
+ */
@Override
public double addEstimateBytesAndMaybeBreak(long bytes, String label) throws CircuitBreakingException {
return 0;
}
+ /**
+ * This is a noop, nothing is added, always return 0
+ * @param bytes number of bytes to add (ignored)
+ * @return always return 0
+ */
@Override
public long addWithoutBreaking(long bytes) {
return 0;
}
+ /**
+ * This is a noop, always return 0
+ * @return always return 0
+ */
@Override
public long getUsed() {
return 0;
}
+ /**
+ * A noop breaker have a constant limit of -1
+ * @return always return -1
+ */
@Override
public long getLimit() {
return LIMIT;
}
+ /**
+ * A noop breaker have no overhead, always return 0
+ * @return always return 0
+ */
@Override
public double getOverhead() {
return 0;
}
+ /**
+ * A noop breaker never trip, always return 0
+ * @return always return 0
+ */
@Override
public long getTrippedCount() {
return 0;
}
+ /**
+ * return the name of this breaker
+ * @return the name of this breaker
+ */
@Override
public String getName() {
return this.name;
}
+ /**
+ * A noop breaker {@link Durability} is always {@link Durability#PERMANENT}
+ * @return always return {@link Durability#PERMANENT }
+ */
@Override
public Durability getDurability() {
return Durability.PERMANENT;
}
+ /**
+ * Limit and overhead are constant for a noop breaker.
+ * this is a noop.
+ * @param limit the desired limit (ignored)
+ * @param overhead the desired overhead (ignored)
+ */
@Override
- public void setLimitAndOverhead(long limit, double overhead) {}
+ public void setLimitAndOverhead(long limit, double overhead) {
+ // noop
+ }
}
diff --git a/libs/core/src/main/java/org/opensearch/core/common/breaker/package-info.java b/libs/core/src/main/java/org/opensearch/core/common/breaker/package-info.java
new file mode 100644
index 0000000000000..f9fb83d2207e1
--- /dev/null
+++ b/libs/core/src/main/java/org/opensearch/core/common/breaker/package-info.java
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * The OpenSearch Contributors require contributions made to
+ * this file be licensed under the Apache-2.0 license or a
+ * compatible open source license.
+ */
+
+/**
+ * Foundation classes for the Circuit Breaker
+ */
+package org.opensearch.core.common.breaker;
diff --git a/libs/core/src/main/java/org/opensearch/core/common/bytes/AbstractBytesReference.java b/libs/core/src/main/java/org/opensearch/core/common/bytes/AbstractBytesReference.java
index e054776d67fdc..8c1efcd00c24e 100644
--- a/libs/core/src/main/java/org/opensearch/core/common/bytes/AbstractBytesReference.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/bytes/AbstractBytesReference.java
@@ -49,7 +49,8 @@
*/
public abstract class AbstractBytesReference implements BytesReference {
- private Integer hash = null; // we cache the hash of this reference since it can be quite costly to re-calculated it
+ /** we cache the hash of this reference since it can be quite costly to re-calculated it */
+ private Integer hash = null;
private static final int MAX_UTF16_LENGTH = Integer.MAX_VALUE >> 1;
@Override
diff --git a/libs/core/src/main/java/org/opensearch/core/common/bytes/BytesReference.java b/libs/core/src/main/java/org/opensearch/core/common/bytes/BytesReference.java
index fc8e62c914e27..9d24d3653397b 100644
--- a/libs/core/src/main/java/org/opensearch/core/common/bytes/BytesReference.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/bytes/BytesReference.java
@@ -35,6 +35,7 @@
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefIterator;
+import org.opensearch.common.annotation.PublicApi;
import org.opensearch.core.common.io.stream.BytesStream;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.util.ByteArray;
@@ -50,8 +51,9 @@
/**
* A reference to bytes.
*
- * @opensearch.internal
+ * @opensearch.api
*/
+@PublicApi(since = "1.0.0")
public interface BytesReference extends Comparable, ToXContentFragment {
/**
diff --git a/libs/core/src/main/java/org/opensearch/core/common/io/stream/NamedWriteableRegistry.java b/libs/core/src/main/java/org/opensearch/core/common/io/stream/NamedWriteableRegistry.java
index ec707f147cade..abac76c8b6c27 100644
--- a/libs/core/src/main/java/org/opensearch/core/common/io/stream/NamedWriteableRegistry.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/io/stream/NamedWriteableRegistry.java
@@ -32,6 +32,8 @@
package org.opensearch.core.common.io.stream;
+import org.opensearch.common.annotation.PublicApi;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -45,15 +47,17 @@
* The registration is keyed by the combination of the category class of {@link NamedWriteable}, and a name unique
* to that category.
*
- * @opensearch.internal
+ * @opensearch.api
*/
+@PublicApi(since = "1.0.0")
public class NamedWriteableRegistry {
/**
* An entry in the registry, made up of a category class and name, and a reader for that category class.
*
- * @opensearch.internal
+ * @opensearch.api
*/
+ @PublicApi(since = "1.0.0")
public static class Entry {
/** The superclass of a {@link NamedWriteable} which will be read by {@link #reader}. */
diff --git a/libs/core/src/main/java/org/opensearch/core/common/io/stream/StreamInput.java b/libs/core/src/main/java/org/opensearch/core/common/io/stream/StreamInput.java
index 24795204c6dc8..ece2012302919 100644
--- a/libs/core/src/main/java/org/opensearch/core/common/io/stream/StreamInput.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/io/stream/StreamInput.java
@@ -46,13 +46,16 @@
import org.opensearch.Version;
import org.opensearch.common.CharArrays;
import org.opensearch.common.Nullable;
+import org.opensearch.common.annotation.PublicApi;
+import org.opensearch.common.unit.TimeValue;
+import org.opensearch.core.common.Strings;
import org.opensearch.core.common.bytes.BytesArray;
import org.opensearch.core.common.bytes.BytesReference;
import org.opensearch.core.common.settings.SecureString;
import org.opensearch.core.common.text.Text;
-import org.opensearch.common.unit.TimeValue;
-import org.opensearch.core.common.Strings;
import org.opensearch.core.concurrency.OpenSearchRejectedExecutionException;
+import org.opensearch.core.xcontent.MediaType;
+import org.opensearch.core.xcontent.MediaTypeRegistry;
import java.io.ByteArrayInputStream;
import java.io.EOFException;
@@ -102,8 +105,9 @@
* lists, either by storing {@code List}s internally or just converting to and from a {@code List} when calling. This comment is repeated
* on {@link StreamInput}.
*
- * @opensearch.internal
+ * @opensearch.api
*/
+@PublicApi(since = "1.0.0")
public abstract class StreamInput extends InputStream {
private Version version = Version.CURRENT;
@@ -344,6 +348,10 @@ public BigInteger readBigInteger() throws IOException {
return new BigInteger(readString());
}
+ public MediaType readMediaType() throws IOException {
+ return MediaTypeRegistry.fromMediaType(readString());
+ }
+
@Nullable
public Text readOptionalText() throws IOException {
int length = readInt();
@@ -716,6 +724,8 @@ public Object readGenericValue() throws IOException {
return readByte();
case 12:
return readDate();
+ case 13:
+ return readZonedDateTime();
case 14:
return readBytesReference();
case 15:
diff --git a/libs/core/src/main/java/org/opensearch/core/common/io/stream/StreamOutput.java b/libs/core/src/main/java/org/opensearch/core/common/io/stream/StreamOutput.java
index 566abf9f08f53..94b813246bc7e 100644
--- a/libs/core/src/main/java/org/opensearch/core/common/io/stream/StreamOutput.java
+++ b/libs/core/src/main/java/org/opensearch/core/common/io/stream/StreamOutput.java
@@ -45,13 +45,14 @@
import org.opensearch.Version;
import org.opensearch.common.CharArrays;
import org.opensearch.common.Nullable;
+import org.opensearch.common.annotation.PublicApi;
+import org.opensearch.common.unit.TimeValue;
import org.opensearch.core.common.bytes.BytesArray;
import org.opensearch.core.common.bytes.BytesReference;
import org.opensearch.core.common.io.stream.Writeable.WriteableRegistry;
import org.opensearch.core.common.io.stream.Writeable.Writer;
import org.opensearch.core.common.settings.SecureString;
import org.opensearch.core.common.text.Text;
-import org.opensearch.common.unit.TimeValue;
import org.opensearch.core.concurrency.OpenSearchRejectedExecutionException;
import java.io.EOFException;
@@ -96,8 +97,9 @@
* lists, either by storing {@code List}s internally or just converting to and from a {@code List} when calling. This comment is repeated
* on {@link StreamInput}.
*
- * @opensearch.internal
+ * @opensearch.api
*/
+@PublicApi(since = "1.0.0")
public abstract class StreamOutput extends OutputStream {
private static final int MAX_NESTED_EXCEPTION_LEVEL = 100;
@@ -804,6 +806,23 @@ private static Class> getGenericType(Object value) {
}
}
+ /**
+ * Returns the registered writer for the given class type.
+ */
+ @SuppressWarnings("unchecked")
+ public static > W getWriter(Class> type) {
+ Writer