This is an automated email from the ASF dual-hosted git repository.
broustant pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr-sandbox.git
The following commit(s) were added to refs/heads/main by this push:
new 4e1819f Support concurrency when reading transaction log encryption
header. (#112)
4e1819f is described below
commit 4e1819ff8a3758becca19bf337ecd1b352dba805
Author: Bruno Roustant <[email protected]>
AuthorDate: Fri Nov 22 15:12:06 2024 +0100
Support concurrency when reading transaction log encryption header. (#112)
---
.../solr/encryption/EncryptionTransactionLog.java | 36 ++++++++++++----------
.../solr/encryption/EncryptionUpdateLog.java | 9 ++----
2 files changed, 21 insertions(+), 24 deletions(-)
diff --git
a/encryption/src/main/java/org/apache/solr/encryption/EncryptionTransactionLog.java
b/encryption/src/main/java/org/apache/solr/encryption/EncryptionTransactionLog.java
index 13f08cf..1da3aa3 100644
---
a/encryption/src/main/java/org/apache/solr/encryption/EncryptionTransactionLog.java
+++
b/encryption/src/main/java/org/apache/solr/encryption/EncryptionTransactionLog.java
@@ -26,7 +26,6 @@ import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
import java.nio.file.Path;
import java.util.Collection;
@@ -140,28 +139,33 @@ public class EncryptionTransactionLog extends
TransactionLog {
*
* @return The key reference number as a string; or null if the log is not
encrypted.
*/
- static String readEncryptionHeader(FileChannel channel, ByteBuffer
readBuffer) throws IOException {
- long position = channel.position();
- if (position != 0) {
- channel.position(0);
- }
- int magic = readBEInt(channel, readBuffer);
+ static String readEncryptionHeader(FileChannel channel) throws IOException {
+ int magic = readBEInt(channel, 0L, false);
String keyRef = null;
if (magic == ENCRYPTION_MAGIC) {
// This file is encrypted.
// Read the key reference that follows.
- keyRef = Integer.toString(readBEInt(channel, readBuffer));
+ keyRef = Integer.toString(readBEInt(channel, 4L, true));
}
- channel.position(position);
return keyRef;
}
- private static int readBEInt(ReadableByteChannel channel, ByteBuffer
readBuffer) throws IOException {
- readBuffer.clear();
- int n = channel.read(readBuffer);
- if (n != 4) {
- throw new EOFException();
+ private static int readBEInt(FileChannel channel, long position, boolean
requireAllBytes) throws IOException {
+ ByteBuffer readBuffer = ByteBuffer.allocate(4);
+ // Read 4 bytes.
+ int bytesRead = channel.read(readBuffer, position);
+ if (bytesRead < 4) {
+ if (requireAllBytes) {
+ throw new EOFException(
+ bytesRead == -1 || bytesRead == 0
+ ? "Header is empty; no data read."
+ : "Incomplete header; expected 4 bytes, but only read " +
bytesRead + " bytes.");
+ } else {
+ // If not requiring all bytes, just return 0.
+ return 0;
+ }
}
+ // Convert the 4 bytes to an integer in big-endian order
return ((readBuffer.get(0) & 0xFF) << 24)
| ((readBuffer.get(1) & 0xFF) << 16)
| ((readBuffer.get(2) & 0xFF) << 8)
@@ -234,20 +238,18 @@ public class EncryptionTransactionLog extends
TransactionLog {
protected final EncryptionDirectorySupplier directorySupplier;
protected final IvHolder ivHolder;
- protected final ByteBuffer readBuffer;
protected EncryptionChannelInputStreamOpener(
EncryptionDirectorySupplier directorySupplier, IvHolder ivHolder) {
this.directorySupplier = directorySupplier;
this.ivHolder = ivHolder;
- readBuffer = ByteBuffer.allocate(4);
}
@Override
public ChannelFastInputStream open(FileChannel channel, long position)
throws IOException {
EncryptionDirectory directory = directorySupplier.get();
try {
- String keyRef = readEncryptionHeader(channel, readBuffer);
+ String keyRef = readEncryptionHeader(channel);
if (keyRef != null) {
// The IndexInput has to be wrapped to be decrypted with the key.
DecryptingChannelInputStream dcis =
diff --git
a/encryption/src/main/java/org/apache/solr/encryption/EncryptionUpdateLog.java
b/encryption/src/main/java/org/apache/solr/encryption/EncryptionUpdateLog.java
index 237a499..db3a706 100644
---
a/encryption/src/main/java/org/apache/solr/encryption/EncryptionUpdateLog.java
+++
b/encryption/src/main/java/org/apache/solr/encryption/EncryptionUpdateLog.java
@@ -29,15 +29,11 @@ import org.apache.solr.update.UpdateLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.invoke.MethodHandles;
-import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
-import java.nio.file.CopyOption;
import java.nio.file.Files;
-import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
@@ -140,10 +136,9 @@ public class EncryptionUpdateLog extends UpdateLog {
throws IOException {
List<TransactionLog> allLogs = getAllLogs();
if (!allLogs.isEmpty()) {
- ByteBuffer readBuffer = ByteBuffer.allocate(4);
for (TransactionLog log : allLogs) {
try (FileChannel logChannel =
FileChannel.open(((EncryptionTransactionLog) log).path(),
StandardOpenOption.READ)) {
- String logKeyRef = readEncryptionHeader(logChannel, readBuffer);
+ String logKeyRef = readEncryptionHeader(logChannel);
String logKeyId = logKeyRef == null ? null :
getKeyIdFromCommit(logKeyRef, commitUserData);
if (!Objects.equals(logKeyId, keyId)) {
return false;
@@ -178,7 +173,7 @@ public class EncryptionUpdateLog extends UpdateLog {
assert log.refCount() <= 1;
if (Files.size(log.path()) > 0) {
try (FileChannel inputChannel = FileChannel.open(log.path(),
StandardOpenOption.READ)) {
- String inputKeyRef = readEncryptionHeader(inputChannel,
ByteBuffer.allocate(4));
+ String inputKeyRef = readEncryptionHeader(inputChannel);
if (!Objects.equals(inputKeyRef, activeKeyRef)) {
Path newLogPath = log.path().resolveSibling(log.path().getFileName()
+ ".enc");
try (OutputStream outputStream = Files.newOutputStream(newLogPath,
StandardOpenOption.CREATE)) {