Author: tomekr Date: Mon Nov 20 11:22:55 2017 New Revision: 1815789 URL: http://svn.apache.org/viewvc?rev=1815789&view=rev Log: OAK-6066: Migration of binaries relies on implementation details of the TarMK
Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/BlobMigrator.java jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/DepthFirstNodeIterator.java jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/migration/AbstractMigratorTest.java jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/migration/DepthFirstNodeIteratorTest.java Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/BlobMigrator.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/BlobMigrator.java?rev=1815789&r1=1815788&r2=1815789&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/BlobMigrator.java (original) +++ jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/BlobMigrator.java Mon Nov 20 11:22:55 2017 @@ -70,16 +70,19 @@ public class BlobMigrator { public BlobMigrator(SplitBlobStore blobStore, NodeStore nodeStore) { this.blobStore = blobStore; this.nodeStore = nodeStore; - refreshAndReset(); } public boolean start() throws IOException { totalMigratedNodes = 0; - refreshAndReset(); + refreshAndReset(nodeStore.getRoot()); return migrate(); } public boolean migrate() throws IOException { + if (nodeIterator == null) { + refreshAndReset(nodeStore.getRoot()); + } + do { while (nodeIterator.hasNext()) { lastPath = nodeIterator.getPath(); @@ -104,15 +107,19 @@ public class BlobMigrator { private boolean tryCommit() { try { - nodeStore.merge(rootBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY); + NodeState newRoot = nodeStore.merge(rootBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY); totalMigratedNodes += migratedNodes; log.info("{} nodes merged succesfully. Nodes migrated in this session: {}", migratedNodes, totalMigratedNodes); lastCommit = System.currentTimeMillis(); migratedNodes = 0; + + rootBuilder = newRoot.builder(); + nodeIterator = nodeIterator.switchRoot(newRoot); + return true; } catch (CommitFailedException e) { log.error("Can't commit. Resetting the migrator", e); - refreshAndReset(); + refreshAndReset(nodeStore.getRoot()); return false; } } @@ -141,8 +148,7 @@ public class BlobMigrator { return totalMigratedNodes; } - private void refreshAndReset() { - NodeState rootState = nodeStore.getRoot(); + private void refreshAndReset(NodeState rootState) { rootBuilder = rootState.builder(); nodeIterator = new DepthFirstNodeIterator(rootState); lastPath = null; Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/DepthFirstNodeIterator.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/DepthFirstNodeIterator.java?rev=1815789&r1=1815788&r2=1815789&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/DepthFirstNodeIterator.java (original) +++ jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/migration/DepthFirstNodeIterator.java Mon Nov 20 11:22:55 2017 @@ -29,20 +29,32 @@ import org.apache.jackrabbit.oak.spi.sta import com.google.common.base.Joiner; import com.google.common.collect.AbstractIterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DepthFirstNodeIterator extends AbstractIterator<ChildNodeEntry> { - private final Deque<Iterator<? extends ChildNodeEntry>> itQueue = new ArrayDeque<Iterator<? extends ChildNodeEntry>>(); + private static final Logger log = LoggerFactory.getLogger(DepthFirstNodeIterator.class); - private final Deque<String> nameQueue = new ArrayDeque<String>(); + private final Deque<Iterator<? extends ChildNodeEntry>> itQueue; + + private final Deque<String> nameQueue; private final NodeState root; public DepthFirstNodeIterator(NodeState root) { this.root = root; + this.itQueue = new ArrayDeque<>(); + this.nameQueue = new ArrayDeque<>(); reset(); } + private DepthFirstNodeIterator(NodeState root, Deque<Iterator<? extends ChildNodeEntry>> itQueue, Deque<String> nameQueue) { + this.root = root; + this.itQueue = itQueue; + this.nameQueue = nameQueue; + } + public void reset() { itQueue.clear(); nameQueue.clear(); @@ -81,4 +93,27 @@ public class DepthFirstNodeIterator exte return Joiner.on('/').appendTo(path, nameQueue).toString(); } + public DepthFirstNodeIterator switchRoot(NodeState newRoot) { + Deque<Iterator<? extends ChildNodeEntry>> newQueue = new ArrayDeque<>(); + NodeState current = newRoot; + for (String name : nameQueue) { + boolean found = false; + Iterator<? extends ChildNodeEntry> it = current.getChildNodeEntries().iterator(); + newQueue.add(it); + while (it.hasNext()) { + ChildNodeEntry e = it.next(); + if (name.equals(e.getName())) { + current = e.getNodeState(); + found = true; + break; + } + } + if (!found) { + log.warn("Can't found {} in the new root. Switching to /", getPath()); + return new DepthFirstNodeIterator(newRoot); + } + } + newQueue.add(current.getChildNodeEntries().iterator()); + return new DepthFirstNodeIterator(newRoot, newQueue, nameQueue); + } } \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/migration/AbstractMigratorTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/migration/AbstractMigratorTest.java?rev=1815789&r1=1815788&r2=1815789&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/migration/AbstractMigratorTest.java (original) +++ jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/migration/AbstractMigratorTest.java Mon Nov 20 11:22:55 2017 @@ -74,6 +74,12 @@ public abstract class AbstractMigratorTe DefaultSplitBlobStore splitBlobStore = new DefaultSplitBlobStore(repository.getPath(), oldBlobStore, newBlobStore); nodeStore = createNodeStore(splitBlobStore, repository); migrator = new BlobMigrator(splitBlobStore, nodeStore); + + // see OAK-6066 + NodeBuilder builder = nodeStore.getRoot().builder(); + builder.setProperty("foo", "bar"); + nodeStore.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY); + } protected abstract NodeStore createNodeStore(BlobStore blobStore, File repository) throws IOException; Modified: jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/migration/DepthFirstNodeIteratorTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/migration/DepthFirstNodeIteratorTest.java?rev=1815789&r1=1815788&r2=1815789&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/migration/DepthFirstNodeIteratorTest.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/migration/DepthFirstNodeIteratorTest.java Mon Nov 20 11:22:55 2017 @@ -96,4 +96,29 @@ public class DepthFirstNodeIteratorTest } assertTrue(nameToPath.isEmpty()); } + + @Test + public void testSwitchRoot() { + Map<String, String[]> subtrees = new HashMap<String, String[]>(); + subtrees.put("uk", new String[] { "cities", "london", "districts", "frognal" }); + subtrees.put("germany", new String[] {}); + subtrees.put("france", new String[] { "cities", "paris" }); + + DepthFirstNodeIterator iterator = new DepthFirstNodeIterator(store.getRoot()); + assertTrue(iterator.hasNext()); + assertEquals("countries", iterator.next().getName()); + + for (int i = 0; i < 3; i++) { + assertTrue(iterator.hasNext()); + String country = iterator.next().getName(); + for (String node : subtrees.remove(country)) { + assertTrue(iterator.hasNext()); + assertEquals(node, iterator.next().getName()); + iterator = iterator.switchRoot(store.getRoot()); + } + } + assertFalse(iterator.hasNext()); + assertTrue(subtrees.isEmpty()); + } + }