diff --git a/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java b/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java index df92d31..7ee0d4b 100644 --- a/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java +++ b/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java @@ -89,18 +89,30 @@ public class CliUtils { }); } - public static void backupOldJcr2Files(String repositoryDirPath) { - // backup old jcr2 files when doing an in-place upgrade + public static void backupOldJcr2Files(String repositoryDirPath, boolean preserveDataStore) { File repositoryDir = new File(repositoryDirPath); File crx2 = new File(repositoryDir, "crx2"); log.info("Moving existing repository under {}", crx2.getAbsolutePath()); crx2.mkdir(); - Pattern pattern = Pattern.compile("crx2|segmentstore"); + + File datastore = new File(repositoryDir, "repository/datastore"); + File tmpDatastore = new File(repositoryDir, "datastore"); + if (preserveDataStore && datastore.isDirectory()) { + log.info("Preserving datastore under {}", datastore.toString()); + datastore.renameTo(tmpDatastore); + } + + Pattern pattern = Pattern.compile("crx2|segmentstore|datastore"); for (File file : repositoryDir.listFiles()) { String name = file.getName(); if (!pattern.matcher(name).matches()) { file.renameTo(new File(crx2, name)); } } + + if (preserveDataStore && tmpDatastore.isDirectory()) { + new File(repositoryDir, "repository").mkdir(); + tmpDatastore.renameTo(datastore); + } } } diff --git a/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java b/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java index 821bbca..1667efe 100644 --- a/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java +++ b/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java @@ -27,6 +27,7 @@ import com.google.common.io.Closer; import org.apache.jackrabbit.oak.spi.lifecycle.CompositeInitializer; import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer; +import org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade; import org.apache.jackrabbit.oak.upgrade.cli.parser.MigrationCliArguments; import org.apache.jackrabbit.oak.upgrade.cli.parser.MigrationOptions; import org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory; @@ -50,7 +51,7 @@ public class OakUpgrade { MigrationFactory factory = new MigrationFactory(options, stores, closer); try { if (stores.getSrcStore().isJcr2()) { - upgrade(factory); + upgrade(stores, factory); } else { sidegrade(factory); } @@ -59,13 +60,14 @@ public class OakUpgrade { } finally { closer.close(); } - if (stores.isInPlaceUpgrade()) { - CliUtils.backupOldJcr2Files(stores.getSrcPaths()[0]); - } } - private static void upgrade(MigrationFactory migrationFactory) throws IOException, RepositoryException { - migrationFactory.createUpgrade().copy(createCompositeInitializer()); + private static void upgrade(StoreArguments stores, MigrationFactory migrationFactory) throws IOException, RepositoryException { + RepositoryUpgrade upgrade = migrationFactory.createUpgrade(); + upgrade.copy(createCompositeInitializer()); + if (stores.isInPlaceUpgrade()) { + CliUtils.backupOldJcr2Files(stores.getSrcPaths()[0], upgrade.isCopyBinariesByReference()); + } } private static void sidegrade(MigrationFactory migrationFactory) throws IOException, RepositoryException { diff --git a/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/InPlaceJcrToSegmentTest.java b/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/InPlaceJcrToSegmentTest.java new file mode 100644 index 0000000..4935b82 --- /dev/null +++ b/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/InPlaceJcrToSegmentTest.java @@ -0,0 +1,93 @@ +/* + * 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.upgrade.cli; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; + +import org.apache.commons.io.FileUtils; +import org.apache.jackrabbit.core.data.FileDataStore; +import org.apache.jackrabbit.oak.jcr.Jcr; +import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl; +import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore; +import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceIndexProvider; +import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore; +import org.apache.jackrabbit.oak.plugins.segment.file.FileStore; +import org.apache.jackrabbit.oak.spi.state.NodeStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.io.Files; + +public class InPlaceJcrToSegmentTest { + + private File repositoryDir; + + private FileStore fs; + + private RepositoryImpl repository; + + private Session session; + + @Before + public void prepare() throws Exception { + repositoryDir = Files.createTempDir(); + Util.unzip(AbstractOak2OakTest.class.getResourceAsStream("/jcr2.zip"), repositoryDir); + + OakUpgrade.main(repositoryDir.getPath()); + + FileDataStore fds = new FileDataStore(); + fds.init(repositoryDir.toString()); + + FileStore.Builder builder = FileStore.newFileStore(new File(repositoryDir, "segmentstore")); + builder.withBlobStore(new DataStoreBlobStore(fds)); + fs = builder.create(); + NodeStore nodeStore = SegmentNodeStore.newSegmentNodeStore(fs).create(); + + repository = (RepositoryImpl) new Jcr(nodeStore).with(new ReferenceIndexProvider()).createRepository(); + session = repository.login(new SimpleCredentials("admin", "admin".toCharArray())); + } + + @After + public void clean() throws IOException { + session.logout(); + repository.shutdown(); + fs.close(); + FileUtils.deleteDirectory(repositoryDir); + } + + @Test + public void validateMigration() throws RepositoryException, IOException { + assertArrayEquals(new String[] { "crx2", "repository", "segmentstore" }, repositoryDir.list()); + assertTrue(new File(repositoryDir, "repository/datastore").exists()); + assertArrayEquals(new String[] { ".lock", "repository", "repository.xml", "version", "workspaces" }, + new File(repositoryDir, "crx2").list()); + assertFalse(new File(repositoryDir, "crx2/repository/datastore").exists()); + + AbstractOak2OakTest.verifyContent(session); + AbstractOak2OakTest.verifyBlob(session); + } +}