You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by to...@apache.org on 2018/09/06 10:31:52 UTC
svn commit: r1840207 - in /jackrabbit/oak/trunk:
oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/
oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/
oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/f...
Author: tomekr
Date: Thu Sep 6 10:31:52 2018
New Revision: 1840207
URL: http://svn.apache.org/viewvc?rev=1840207&view=rev
Log:
OAK-7735: Support the split persistence in the SegmentNodeStoreService.
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitPersistence.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitSegmentArchiveManager.java
Modified:
jackrabbit/oak/trunk/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentTarManager.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/SegmentArchiveManager.java
Modified: jackrabbit/oak/trunk/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java?rev=1840207&r1=1840206&r2=1840207&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java (original)
+++ jackrabbit/oak/trunk/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java Thu Sep 6 10:31:52 2018
@@ -98,6 +98,12 @@ public class AzureArchiveManager impleme
}
@Override
+ public SegmentArchiveReader forceOpen(String archiveName) throws IOException {
+ CloudBlobDirectory archiveDirectory = getDirectory(archiveName);
+ return new AzureSegmentArchiveReader(archiveDirectory, ioMonitor);
+ }
+
+ @Override
public SegmentArchiveWriter create(String archiveName) throws IOException {
return new AzureSegmentArchiveWriter(getDirectory(archiveName), ioMonitor, monitor);
}
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java?rev=1840207&r1=1840206&r2=1840207&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java Thu Sep 6 10:31:52 2018
@@ -248,6 +248,12 @@ public class SegmentNodeStoreFactory {
boolean customSegmentStore() default false;
@AttributeDefinition(
+ name = "Split persistence",
+ description = "Boolean value indicating that the writes should be done locally when using the custom segment store"
+ )
+ boolean splitPersistence() default false;
+
+ @AttributeDefinition(
name = "Backup directory",
description = "Directory (relative to current working directory) for storing repository backups. " +
"Defaults to 'repository.home/segmentstore-backup'."
@@ -467,6 +473,11 @@ public class SegmentNodeStoreFactory {
}
@Override
+ public File getSplitPersistenceDirectory() {
+ return new File(getRepositoryHome(), appendRole("segmentstore-split"));
+ }
+
+ @Override
public int getSegmentCacheSize() {
return getCacheSize("segmentCache.size", configuration.segmentCache_size());
}
@@ -517,6 +528,11 @@ public class SegmentNodeStoreFactory {
}
@Override
+ public boolean hasSplitPersistence() {
+ return configuration.splitPersistence();
+ }
+
+ @Override
public boolean registerDescriptors() {
return configuration.registerDescriptors();
}
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java?rev=1840207&r1=1840206&r2=1840207&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java Thu Sep 6 10:31:52 2018
@@ -58,7 +58,9 @@ import org.apache.jackrabbit.oak.segment
import org.apache.jackrabbit.oak.segment.file.FileStoreStatsMBean;
import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
import org.apache.jackrabbit.oak.segment.file.MetricsIOMonitor;
+import org.apache.jackrabbit.oak.segment.file.tar.TarPersistence;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentNodeStorePersistence;
+import org.apache.jackrabbit.oak.segment.split.SplitPersistence;
import org.apache.jackrabbit.oak.spi.blob.BlobStore;
import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
import org.apache.jackrabbit.oak.spi.cluster.ClusterRepositoryInfo;
@@ -116,6 +118,8 @@ class SegmentNodeStoreRegistrar {
File getSegmentDirectory();
+ File getSplitPersistenceDirectory();
+
int getSegmentCacheSize();
int getStringCacheSize();
@@ -136,6 +140,8 @@ class SegmentNodeStoreRegistrar {
boolean hasCustomSegmentStore();
+ boolean hasSplitPersistence();
+
boolean registerDescriptors();
String getRepositoryHome();
@@ -228,8 +234,17 @@ class SegmentNodeStoreRegistrar {
}
if (cfg.hasCustomSegmentStore() && cfg.getSegmentNodeStorePersistence() != null) {
- cfg.getLogger().info("Initializing SegmentNodeStore with custom persistence [{}]", cfg.getSegmentNodeStorePersistence());
- builder.withCustomPersistence(cfg.getSegmentNodeStorePersistence());
+ if (cfg.hasSplitPersistence()) {
+ cfg.getLogger().info("Initializing SegmentNodeStore with custom persistence [{}] and local writes", cfg.getSegmentNodeStorePersistence());
+ cfg.getSplitPersistenceDirectory().mkdirs();
+ SegmentNodeStorePersistence roPersistence = cfg.getSegmentNodeStorePersistence();
+ SegmentNodeStorePersistence rwPersistence = new TarPersistence(cfg.getSplitPersistenceDirectory());
+ SegmentNodeStorePersistence persistence = new SplitPersistence(roPersistence, rwPersistence);
+ builder.withCustomPersistence(persistence);
+ } else {
+ cfg.getLogger().info("Initializing SegmentNodeStore with custom persistence [{}]", cfg.getSegmentNodeStorePersistence());
+ builder.withCustomPersistence(cfg.getSegmentNodeStorePersistence());
+ }
}
if (cfg.isStandbyInstance()) {
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java?rev=1840207&r1=1840206&r2=1840207&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java Thu Sep 6 10:31:52 2018
@@ -246,6 +246,12 @@ public class SegmentNodeStoreService {
boolean customSegmentStore() default false;
@AttributeDefinition(
+ name = "Split persistence",
+ description = "Boolean value indicating that the writes should be done locally when using the custom segment store"
+ )
+ boolean splitPersistence() default false;
+
+ @AttributeDefinition(
name = "Backup directory",
description = "Directory (relative to current working directory) for storing repository backups. " +
"Defaults to 'repository.home/segmentstore-backup'."
@@ -403,6 +409,11 @@ public class SegmentNodeStoreService {
}
@Override
+ public File getSplitPersistenceDirectory() {
+ return new File(getRepositoryHome(), "segmentstore-split");
+ }
+
+ @Override
public int getSegmentCacheSize() {
Integer size = Integer.getInteger("segmentCache.size");
if (size != null) {
@@ -473,6 +484,11 @@ public class SegmentNodeStoreService {
}
@Override
+ public boolean hasSplitPersistence() {
+ return configuration.splitPersistence();
+ }
+
+ @Override
public boolean registerDescriptors() {
return true;
}
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentTarManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentTarManager.java?rev=1840207&r1=1840206&r2=1840207&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentTarManager.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentTarManager.java Thu Sep 6 10:31:52 2018
@@ -116,6 +116,11 @@ public class SegmentTarManager implement
}
@Override
+ public SegmentArchiveReader forceOpen(String archiveName) throws IOException {
+ return open(archiveName);
+ }
+
+ @Override
public SegmentArchiveWriter create(String archiveName) {
return new SegmentTarWriter(new File(segmentstoreDir, archiveName), fileStoreMonitor, ioMonitor);
}
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/SegmentArchiveManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/SegmentArchiveManager.java?rev=1840207&r1=1840206&r2=1840207&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/SegmentArchiveManager.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/SegmentArchiveManager.java Thu Sep 6 10:31:52 2018
@@ -47,12 +47,23 @@ public interface SegmentArchiveManager {
* Opens a given archive for reading.
*
* @param archiveName
- * @return the archive reader or null if the archive doesn't exist
+ * @return the archive reader or null if the archive doesn't exist or doesn't
+ * have a valid index
*/
@Nullable
SegmentArchiveReader open(@NotNull String archiveName) throws IOException;
/**
+ * Opens an archive that wasn't closed correctly.
+ *
+ * @param archiveName
+ * @return the archive reader or null if the implementation doesn't support
+ * opening an unclosed archive
+ */
+ @Nullable
+ SegmentArchiveReader forceOpen(String archiveName) throws IOException;
+
+ /**
* Creates a new archive.
*
* @param archiveName
Added: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitPersistence.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitPersistence.java?rev=1840207&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitPersistence.java (added)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitPersistence.java Thu Sep 6 10:31:52 2018
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.segment.split;
+
+import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitor;
+import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitorAdapter;
+import org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitor;
+import org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitorAdapter;
+import org.apache.jackrabbit.oak.segment.spi.persistence.GCJournalFile;
+import org.apache.jackrabbit.oak.segment.spi.persistence.JournalFile;
+import org.apache.jackrabbit.oak.segment.spi.persistence.JournalFileReader;
+import org.apache.jackrabbit.oak.segment.spi.persistence.JournalFileWriter;
+import org.apache.jackrabbit.oak.segment.spi.persistence.ManifestFile;
+import org.apache.jackrabbit.oak.segment.spi.persistence.RepositoryLock;
+import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveManager;
+import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentNodeStorePersistence;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Properties;
+
+public class SplitPersistence implements SegmentNodeStorePersistence {
+
+ private final SegmentNodeStorePersistence roPersistence;
+
+ private final SegmentNodeStorePersistence rwPersistence;
+
+ private final Optional<String> lastRoArchive;
+
+ public SplitPersistence(SegmentNodeStorePersistence roPersistence, SegmentNodeStorePersistence rwPersistence) throws IOException {
+ this.roPersistence = roPersistence;
+ this.rwPersistence = rwPersistence;
+
+ ManifestFile manifest = rwPersistence.getManifestFile();
+ if (!manifest.exists()) {
+ initialize();
+ }
+ Properties properties = manifest.load();
+ lastRoArchive = Optional.ofNullable(properties.getProperty("split.lastRoArchive"));
+ }
+
+ private void initialize() throws IOException {
+ Properties properties = roPersistence.getManifestFile().load();
+ properties.setProperty("split.initialized", "true");
+ Optional<String> lastArchive = getLastArchive();
+ lastArchive.ifPresent(a -> properties.setProperty("split.lastRoArchive", a));
+ rwPersistence.getManifestFile().save(properties);
+
+ GCJournalFile gcJournalFile = rwPersistence.getGCJournalFile();
+ for (String line : roPersistence.getGCJournalFile().readLines()) {
+ gcJournalFile.writeLine(line);
+ }
+
+ List<String> journalLines = new ArrayList<>();
+ try (JournalFileReader journalFileReader = roPersistence.getJournalFile().openJournalReader()) {
+ String journalLine;
+ while ((journalLine = journalFileReader.readLine()) != null) {
+ journalLines.add(journalLine);
+ }
+ }
+
+ Collections.reverse(journalLines);
+
+ try (JournalFileWriter journalFileWriter = rwPersistence.getJournalFile().openJournalWriter()) {
+ for (String line : journalLines) {
+ journalFileWriter.writeLine(line);
+ }
+ }
+ }
+
+ private Optional<String> getLastArchive() throws IOException {
+ SegmentArchiveManager manager = roPersistence.createArchiveManager(false, new IOMonitorAdapter(), new FileStoreMonitorAdapter());
+ List<String> archives = manager.listArchives();
+ if (archives.isEmpty()) {
+ return Optional.empty();
+ } else {
+ Collections.sort(archives);
+ return Optional.of(archives.get(archives.size() - 1));
+ }
+ }
+
+ @Override
+ public SegmentArchiveManager createArchiveManager(boolean memoryMapping, IOMonitor ioMonitor, FileStoreMonitor fileStoreMonitor) throws IOException {
+ if (lastRoArchive.isPresent()) {
+ return new SplitSegmentArchiveManager(
+ roPersistence.createArchiveManager(memoryMapping, ioMonitor, fileStoreMonitor),
+ rwPersistence.createArchiveManager(memoryMapping, ioMonitor, fileStoreMonitor),
+ lastRoArchive.get());
+ } else {
+ return rwPersistence.createArchiveManager(memoryMapping, ioMonitor, fileStoreMonitor);
+ }
+ }
+
+ @Override
+ public boolean segmentFilesExist() {
+ return lastRoArchive.isPresent() || rwPersistence.segmentFilesExist();
+ }
+
+ @Override
+ public JournalFile getJournalFile() {
+ return rwPersistence.getJournalFile();
+ }
+
+ @Override
+ public GCJournalFile getGCJournalFile() throws IOException {
+ return rwPersistence.getGCJournalFile();
+ }
+
+ @Override
+ public ManifestFile getManifestFile() throws IOException {
+ return rwPersistence.getManifestFile();
+ }
+
+ @Override
+ public RepositoryLock lockRepository() throws IOException {
+ return rwPersistence.lockRepository();
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitSegmentArchiveManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitSegmentArchiveManager.java?rev=1840207&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitSegmentArchiveManager.java (added)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitSegmentArchiveManager.java Thu Sep 6 10:31:52 2018
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.segment.split;
+
+import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveManager;
+import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveReader;
+import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveWriter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.UUID;
+
+public class SplitSegmentArchiveManager implements SegmentArchiveManager {
+
+ private final SegmentArchiveManager roArchiveManager;
+
+ private final SegmentArchiveManager rwArchiveManager;
+
+ private final List<String> roArchiveList;
+
+ public SplitSegmentArchiveManager(SegmentArchiveManager roArchiveManager, SegmentArchiveManager rwArchiveManager, String lastRoArchive) throws IOException {
+ this.roArchiveManager = roArchiveManager;
+ this.rwArchiveManager = rwArchiveManager;
+ this.roArchiveList = getRoArchives(lastRoArchive);
+ }
+
+ private List<String> getRoArchives(String lastRoArchive) throws IOException {
+ List<String> archives = roArchiveManager.listArchives();
+ Collections.sort(archives);
+ int index = archives.indexOf(lastRoArchive);
+ if (index == -1) {
+ throw new IllegalStateException("Can't find archive " + lastRoArchive + " in the read-only persistence");
+ }
+ return new ArrayList<>(archives.subList(0, index + 1));
+ }
+
+ @Override
+ public @NotNull List<String> listArchives() throws IOException {
+ List<String> result = new ArrayList<>();
+ result.addAll(roArchiveList);
+ result.addAll(rwArchiveManager.listArchives());
+ return result;
+ }
+
+ @Override
+ public @Nullable SegmentArchiveReader open(@NotNull String archiveName) throws IOException {
+ if (roArchiveList.contains(archiveName)) {
+ try {
+ return roArchiveManager.open(archiveName);
+ } catch (IOException e) {
+ return roArchiveManager.forceOpen(archiveName);
+ }
+ } else {
+ return rwArchiveManager.open(archiveName);
+ }
+ }
+
+ @Override
+ public @Nullable SegmentArchiveReader forceOpen(String archiveName) throws IOException {
+ if (roArchiveList.contains(archiveName)) {
+ return roArchiveManager.forceOpen(archiveName);
+ } else {
+ return rwArchiveManager.forceOpen(archiveName);
+ }
+ }
+
+ @Override
+ public @NotNull SegmentArchiveWriter create(@NotNull String archiveName) throws IOException {
+ return rwArchiveManager.create(archiveName);
+ }
+
+ @Override
+ public boolean delete(@NotNull String archiveName) {
+ if (roArchiveList.contains(archiveName)) {
+ return false;
+ } else {
+ return rwArchiveManager.delete(archiveName);
+ }
+ }
+
+ @Override
+ public boolean renameTo(@NotNull String from, @NotNull String to) {
+ if (roArchiveList.contains(from) || roArchiveList.contains(to)) {
+ return false;
+ } else {
+ return rwArchiveManager.renameTo(from, to);
+ }
+ }
+
+ @Override
+ public void copyFile(@NotNull String from, @NotNull String to) throws IOException {
+ if (roArchiveList.contains(to)) {
+ throw new IOException("Can't overwrite the read-only " + to);
+ } else if (roArchiveList.contains(from)) {
+ throw new IOException("Can't copy the archive between persistances " + from + " -> " + to);
+ } else {
+ rwArchiveManager.copyFile(from, to);
+ }
+ }
+
+ @Override
+ public boolean exists(@NotNull String archiveName) {
+ return roArchiveList.contains(archiveName) || rwArchiveManager.exists(archiveName);
+ }
+
+ @Override
+ public void recoverEntries(@NotNull String archiveName, @NotNull LinkedHashMap<UUID, byte[]> entries) throws IOException {
+ if (roArchiveList.contains(archiveName)) {
+ roArchiveManager.recoverEntries(archiveName, entries);
+ } else {
+ rwArchiveManager.recoverEntries(archiveName, entries);
+ }
+ }
+}