/* * Copyright © 2014 Cask Data, Inc. * * Licensed 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 co.cask.cdap.data2.transaction.distributed; import co.cask.cdap.common.conf.CConfiguration; import co.cask.cdap.common.conf.Constants; import co.cask.cdap.common.guice.ConfigModule; import co.cask.cdap.common.guice.DiscoveryRuntimeModule; import co.cask.cdap.common.guice.LocationRuntimeModule; import co.cask.cdap.common.guice.ZKClientModule; import co.cask.cdap.common.utils.Networks; import co.cask.cdap.data.runtime.DataFabricModules; import co.cask.cdap.data.runtime.DataSetsModules; import co.cask.cdap.data.runtime.TransactionMetricsModule; import co.cask.cdap.data2.metadata.store.MetadataStore; import co.cask.cdap.data2.metadata.store.NoOpMetadataStore; import co.cask.tephra.Transaction; import co.cask.tephra.TransactionSystemClient; import co.cask.tephra.TransactionSystemTest; import co.cask.tephra.TxConstants; import co.cask.tephra.distributed.TransactionService; import co.cask.tephra.persist.TransactionSnapshot; import co.cask.tephra.persist.TransactionStateStorage; import co.cask.tephra.snapshot.SnapshotCodecProvider; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.util.Modules; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.twill.internal.zookeeper.InMemoryZKServer; import org.apache.twill.zookeeper.ZKClientService; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import java.io.InputStream; /** * HBase queue tests. */ public class TransactionServiceClientTest extends TransactionSystemTest { @ClassRule public static TemporaryFolder tmpFolder = new TemporaryFolder(); private static CConfiguration cConf; private static InMemoryZKServer zkServer; private static TransactionService server; private static TransactionStateStorage txStateStorage; private static ZKClientService zkClient; private static Injector injector; @Override protected TransactionSystemClient getClient() throws Exception { return injector.getInstance(TransactionSystemClient.class); } @Override protected TransactionStateStorage getStateStorage() throws Exception { return txStateStorage; } @BeforeClass public static void beforeClass() throws Exception { HBaseTestingUtility hBaseTestingUtility = new HBaseTestingUtility(); hBaseTestingUtility.startMiniDFSCluster(1); Configuration hConf = hBaseTestingUtility.getConfiguration(); hConf.setBoolean("fs.hdfs.impl.disable.cache", true); zkServer = InMemoryZKServer.builder().build(); zkServer.startAndWait(); cConf = CConfiguration.create(); // tests should use the current user for HDFS cConf.set(Constants.CFG_HDFS_USER, System.getProperty("user.name")); cConf.set(Constants.Zookeeper.QUORUM, zkServer.getConnectionStr()); cConf.set(Constants.CFG_LOCAL_DATA_DIR, tmpFolder.newFolder().getAbsolutePath()); // we want persisting for this test cConf.setBoolean(TxConstants.Manager.CFG_DO_PERSIST, true); server = TransactionServiceTest.createTxService(zkServer.getConnectionStr(), Networks.getRandomPort(), hConf, tmpFolder.newFolder()); server.startAndWait(); injector = Guice.createInjector( new ConfigModule(cConf, hConf), new ZKClientModule(), new LocationRuntimeModule().getInMemoryModules(), new DiscoveryRuntimeModule().getDistributedModules(), new TransactionMetricsModule(), new DataFabricModules().getDistributedModules(), Modules.override(new DataSetsModules().getDistributedModules()).with(new AbstractModule() { @Override protected void configure() { bind(MetadataStore.class).to(NoOpMetadataStore.class); } })); zkClient = injector.getInstance(ZKClientService.class); zkClient.startAndWait(); txStateStorage = injector.getInstance(TransactionStateStorage.class); txStateStorage.startAndWait(); } @AfterClass public static void afterClass() throws Exception { try { try { server.stopAndWait(); } finally { zkClient.stopAndWait(); txStateStorage.stopAndWait(); } } finally { zkServer.stopAndWait(); txStateStorage.stopAndWait(); } } @Before public void resetState() throws Exception { TransactionSystemClient txClient = getClient(); txClient.resetState(); } @Test public void testGetSnapshot() throws Exception { TransactionSystemClient client = getClient(); SnapshotCodecProvider codecProvider = new SnapshotCodecProvider(injector.getInstance(Configuration.class)); Transaction tx1 = client.startShort(); long currentTime = System.currentTimeMillis(); InputStream in = client.getSnapshotInputStream(); TransactionSnapshot snapshot; try { snapshot = codecProvider.decode(in); } finally { in.close(); } Assert.assertTrue(snapshot.getTimestamp() >= currentTime); Assert.assertTrue(snapshot.getInProgress().containsKey(tx1.getWritePointer())); // Ensures that getSnapshot didn't persist a snapshot TransactionSnapshot snapshotAfter = getStateStorage().getLatestSnapshot(); if (snapshotAfter != null) { Assert.assertTrue(snapshot.getTimestamp() > snapshotAfter.getTimestamp()); } } }