/** * 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.hadoop.hdfs.server.namenode.bookkeeper.metadata; import com.google.common.collect.ImmutableSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hdfs.protocol.FSConstants; import org.apache.hadoop.hdfs.server.namenode.bookkeeper.BookKeeperSetupUtil; import org.apache.hadoop.hdfs.server.namenode.bookkeeper.zk.BasicZooKeeper; import org.apache.hadoop.hdfs.server.namenode.bookkeeper.zk.RecoveringZooKeeper; import org.apache.hadoop.hdfs.server.namenode.bookkeeper.zk.ZooKeeperIface; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.TreeSet; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; public class TestBookKeeperJournalMetadataManager extends BookKeeperSetupUtil { private static final Log LOG = LogFactory.getLog(TestBookKeeperJournalMetadataManager.class); // ZooKeeper namespace to use for this test private static final String TEST_ZK_PARENT = "/testBookKeeperJournalMetadataManager"; private BookKeeperJournalMetadataManager manager; @Before public void setUp() throws Exception { super.setUp(); LOG.info("Initializing new BookKeeperJournalMetataManager instance for " + TEST_ZK_PARENT); manager = new BookKeeperJournalMetadataManager( getRecoveringZookeeperClient(), TEST_ZK_PARENT); manager.init(); } @After public void tearDown() throws Exception { super.tearDown(); if (getRecoveringZookeeperClient() != null) { LOG.info("Clearing out " + TEST_ZK_PARENT + " from previous test"); zkDeleteRecursively(TEST_ZK_PARENT); } } @Test public void testReadAndWriteEditLogLedgerMetadata() throws Exception { assertNull("Should return null if ZNode does not exist", manager.readEditLogLedgerMetadata("/does/not/exist")); EditLogLedgerMetadata metadata_1_100 = new EditLogLedgerMetadata( FSConstants.LAYOUT_VERSION, 1, 1, 100); String fullyQualifiedPath_1_100 = manager.fullyQualifiedPathForLedger(metadata_1_100); assertTrue("Should return true if ZNode is created", manager.writeEditLogLedgerMetadata(fullyQualifiedPath_1_100, metadata_1_100)); assertFalse("Should return false if ZNode already exists", manager.writeEditLogLedgerMetadata(fullyQualifiedPath_1_100, metadata_1_100)); assertEquals("Should read be able to correctly read the written metadata", manager.readEditLogLedgerMetadata(fullyQualifiedPath_1_100), metadata_1_100); } @Test public void testVerifyEditLogLedgerMetadata() throws Exception { EditLogLedgerMetadata m0 = new EditLogLedgerMetadata( FSConstants.LAYOUT_VERSION, 1, 1, 100); EditLogLedgerMetadata m1 = new EditLogLedgerMetadata( FSConstants.LAYOUT_VERSION, 2, 101, 200); String m0Path = manager.fullyQualifiedPathForLedger(m0); String m1Path = manager.fullyQualifiedPathForLedger(m1); manager.writeEditLogLedgerMetadata(m0Path, m0); manager.writeEditLogLedgerMetadata(m1Path, m1); assertTrue(m0 + " should verify under " + m0Path, manager.verifyEditLogLedgerMetadata(m0, m0Path)); assertTrue(m1 + " should verify under " + m1Path, manager.verifyEditLogLedgerMetadata(m1, m1Path)); assertFalse(m0 + " should not verify under " + m1Path, manager.verifyEditLogLedgerMetadata(m0, m1Path)); assertFalse(m1 + " should not verify under" + m0Path, manager.verifyEditLogLedgerMetadata(m1, m0Path)); assertFalse("Non-existent path should not verify!", manager.verifyEditLogLedgerMetadata(m0, "/does/not/exist")); } @Test public void testListLedgers() throws Exception { Set<EditLogLedgerMetadata> metadata = ImmutableSet.of( new EditLogLedgerMetadata(FSConstants.LAYOUT_VERSION, 1, 1, 100), new EditLogLedgerMetadata(FSConstants.LAYOUT_VERSION, 2, 101, 200), new EditLogLedgerMetadata(FSConstants.LAYOUT_VERSION, 3, 201, -1), new EditLogLedgerMetadata(FSConstants.LAYOUT_VERSION - 1, 4, 11, -1), new EditLogLedgerMetadata(FSConstants.LAYOUT_VERSION - 1, 5, 2, 10)); for (EditLogLedgerMetadata e : metadata) { String fullLedgerPath = manager.fullyQualifiedPathForLedger(e); manager.writeEditLogLedgerMetadata(fullLedgerPath, e); } Collection<EditLogLedgerMetadata> allLedgers = manager.listLedgers(true); assertTrue("listLedgers(true) returns all ledgers and all ledgers once", allLedgers.containsAll(metadata) && metadata.containsAll(allLedgers)); EditLogLedgerMetadata prev = null; for (EditLogLedgerMetadata curr : allLedgers) { if (prev != null) { assertTrue("List must be ordered by firsTxId", prev.getFirstTxId() <= curr.getFirstTxId()); } prev = curr; } Collection<EditLogLedgerMetadata> finalizedOnly = manager.listLedgers(false); for (EditLogLedgerMetadata e : finalizedOnly) { assertFalse("listLedgers(false) does not return in-progress ledgers" + e, e.getLastTxId() == -1); } TreeSet<EditLogLedgerMetadata> expectedFinalizedOnly = new TreeSet<EditLogLedgerMetadata>(); for (EditLogLedgerMetadata e : allLedgers) { if (e.getLastTxId() != -1) { expectedFinalizedOnly.add(e); } } assertTrue("listLedgers(false) returns all finalized ledgers", finalizedOnly.containsAll(expectedFinalizedOnly) && expectedFinalizedOnly.containsAll(finalizedOnly)); } }