Java tutorial
/* * 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.accumulo.test.proxy; import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.net.InetAddress; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.TimeUnit; import org.apache.accumulo.cluster.ClusterUser; import org.apache.accumulo.core.client.ClientConfiguration; import org.apache.accumulo.core.client.Connector; import org.apache.accumulo.core.client.Instance; import org.apache.accumulo.core.client.impl.Namespaces; import org.apache.accumulo.core.client.security.tokens.KerberosToken; import org.apache.accumulo.core.client.security.tokens.PasswordToken; import org.apache.accumulo.core.conf.DefaultConfiguration; import org.apache.accumulo.core.conf.Property; import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.file.FileOperations; import org.apache.accumulo.core.file.FileSKVWriter; import org.apache.accumulo.core.iterators.DebugIterator; import org.apache.accumulo.core.iterators.DevNull; import org.apache.accumulo.core.iterators.SortedKeyValueIterator; import org.apache.accumulo.core.iterators.user.SummingCombiner; import org.apache.accumulo.core.iterators.user.VersioningIterator; import org.apache.accumulo.core.metadata.MetadataTable; import org.apache.accumulo.core.security.Authorizations; import org.apache.accumulo.core.util.ByteBufferUtil; import org.apache.accumulo.examples.simple.constraints.MaxMutationSize; import org.apache.accumulo.examples.simple.constraints.NumericValueConstraint; import org.apache.accumulo.harness.MiniClusterHarness; import org.apache.accumulo.harness.SharedMiniClusterBase; import org.apache.accumulo.harness.TestingKdc; import org.apache.accumulo.minicluster.impl.MiniAccumuloClusterImpl; import org.apache.accumulo.proxy.Proxy; import org.apache.accumulo.proxy.thrift.AccumuloProxy.Client; import org.apache.accumulo.proxy.thrift.AccumuloSecurityException; import org.apache.accumulo.proxy.thrift.ActiveCompaction; import org.apache.accumulo.proxy.thrift.ActiveScan; import org.apache.accumulo.proxy.thrift.BatchScanOptions; import org.apache.accumulo.proxy.thrift.Column; import org.apache.accumulo.proxy.thrift.ColumnUpdate; import org.apache.accumulo.proxy.thrift.CompactionReason; import org.apache.accumulo.proxy.thrift.CompactionStrategyConfig; import org.apache.accumulo.proxy.thrift.CompactionType; import org.apache.accumulo.proxy.thrift.Condition; import org.apache.accumulo.proxy.thrift.ConditionalStatus; import org.apache.accumulo.proxy.thrift.ConditionalUpdates; import org.apache.accumulo.proxy.thrift.ConditionalWriterOptions; import org.apache.accumulo.proxy.thrift.DiskUsage; import org.apache.accumulo.proxy.thrift.IteratorScope; import org.apache.accumulo.proxy.thrift.IteratorSetting; import org.apache.accumulo.proxy.thrift.Key; import org.apache.accumulo.proxy.thrift.KeyValue; import org.apache.accumulo.proxy.thrift.MutationsRejectedException; import org.apache.accumulo.proxy.thrift.NamespaceExistsException; import org.apache.accumulo.proxy.thrift.NamespaceNotEmptyException; import org.apache.accumulo.proxy.thrift.NamespaceNotFoundException; import org.apache.accumulo.proxy.thrift.NamespacePermission; import org.apache.accumulo.proxy.thrift.PartialKey; import org.apache.accumulo.proxy.thrift.Range; import org.apache.accumulo.proxy.thrift.ScanColumn; import org.apache.accumulo.proxy.thrift.ScanOptions; import org.apache.accumulo.proxy.thrift.ScanResult; import org.apache.accumulo.proxy.thrift.ScanState; import org.apache.accumulo.proxy.thrift.ScanType; import org.apache.accumulo.proxy.thrift.SystemPermission; import org.apache.accumulo.proxy.thrift.TableExistsException; import org.apache.accumulo.proxy.thrift.TableNotFoundException; import org.apache.accumulo.proxy.thrift.TablePermission; import org.apache.accumulo.proxy.thrift.TimeType; import org.apache.accumulo.proxy.thrift.UnknownScanner; import org.apache.accumulo.proxy.thrift.UnknownWriter; import org.apache.accumulo.proxy.thrift.WriterOptions; import org.apache.accumulo.server.util.PortUtils; import org.apache.accumulo.test.functional.SlowIterator; import org.apache.commons.io.FileUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.CommonConfigurationKeysPublic; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileUtil; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.Text; import org.apache.hadoop.security.UserGroupInformation; import org.apache.thrift.TApplicationException; import org.apache.thrift.TException; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.TServer; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Iterators; import com.google.common.net.HostAndPort; /** * Call every method on the proxy and try to verify that it works. */ public abstract class SimpleProxyBase extends SharedMiniClusterBase { private static final Logger log = LoggerFactory.getLogger(SimpleProxyBase.class); @Override protected int defaultTimeoutSeconds() { return 60; } private static final long ZOOKEEPER_PROPAGATION_TIME = 10 * 1000; private static TServer proxyServer; private static int proxyPort; private TestProxyClient proxyClient; private org.apache.accumulo.proxy.thrift.AccumuloProxy.Client client; private static Map<String, String> properties = new HashMap<>(); private static String hostname, proxyPrincipal, proxyPrimary, clientPrincipal; private static File proxyKeytab, clientKeytab; private ByteBuffer creds = null; // Implementations can set this static TProtocolFactory factory = null; private static void waitForAccumulo(Connector c) throws Exception { Iterators.size(c.createScanner(MetadataTable.NAME, Authorizations.EMPTY).iterator()); } private static boolean isKerberosEnabled() { return SharedMiniClusterBase.TRUE.equals(System.getProperty(MiniClusterHarness.USE_KERBEROS_FOR_IT_OPTION)); } /** * Does the actual test setup, invoked by the concrete test class */ public static void setUpProxy() throws Exception { assertNotNull("Implementations must initialize the TProtocolFactory", factory); Connector c = SharedMiniClusterBase.getConnector(); Instance inst = c.getInstance(); waitForAccumulo(c); hostname = InetAddress.getLocalHost().getCanonicalHostName(); Properties props = new Properties(); props.put("instance", inst.getInstanceName()); props.put("zookeepers", inst.getZooKeepers()); final String tokenClass; if (isKerberosEnabled()) { tokenClass = KerberosToken.class.getName(); TestingKdc kdc = getKdc(); // Create a principal+keytab for the proxy proxyKeytab = new File(kdc.getKeytabDir(), "proxy.keytab"); hostname = InetAddress.getLocalHost().getCanonicalHostName(); // Set the primary because the client needs to know it proxyPrimary = "proxy"; // Qualify with an instance proxyPrincipal = proxyPrimary + "/" + hostname; kdc.createPrincipal(proxyKeytab, proxyPrincipal); // Tack on the realm too proxyPrincipal = kdc.qualifyUser(proxyPrincipal); props.setProperty("kerberosPrincipal", proxyPrincipal); props.setProperty("kerberosKeytab", proxyKeytab.getCanonicalPath()); props.setProperty("thriftServerType", "sasl"); // Enabled kerberos auth Configuration conf = new Configuration(false); conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, "kerberos"); UserGroupInformation.setConfiguration(conf); // Login for the Proxy itself UserGroupInformation.loginUserFromKeytab(proxyPrincipal, proxyKeytab.getAbsolutePath()); // User for tests ClusterUser user = kdc.getRootUser(); clientPrincipal = user.getPrincipal(); clientKeytab = user.getKeytab(); } else { clientPrincipal = "root"; tokenClass = PasswordToken.class.getName(); properties.put("password", SharedMiniClusterBase.getRootPassword()); hostname = "localhost"; } props.put("tokenClass", tokenClass); ClientConfiguration clientConfig = SharedMiniClusterBase.getCluster().getClientConfig(); String clientConfPath = new File(SharedMiniClusterBase.getCluster().getConfig().getConfDir(), "client.conf") .getAbsolutePath(); props.put("clientConfigurationFile", clientConfPath); properties.put("clientConfigurationFile", clientConfPath); proxyPort = PortUtils.getRandomFreePort(); proxyServer = Proxy.createProxyServer(HostAndPort.fromParts(hostname, proxyPort), factory, props, clientConfig).server; while (!proxyServer.isServing()) sleepUninterruptibly(100, TimeUnit.MILLISECONDS); } @AfterClass public static void tearDownProxy() throws Exception { if (null != proxyServer) { proxyServer.stop(); } } final IteratorSetting setting = new IteratorSetting(100, "slow", SlowIterator.class.getName(), Collections.singletonMap("sleepTime", "200")); String tableName; String namespaceName; ByteBuffer badLogin; @Before public void setup() throws Exception { // Create a new client for each test if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); proxyClient = new TestProxyClient(hostname, proxyPort, factory, proxyPrimary, UserGroupInformation.getCurrentUser()); client = proxyClient.proxy(); creds = client.login(clientPrincipal, properties); TestingKdc kdc = getKdc(); final ClusterUser user = kdc.getClientPrincipal(0); // Create another user client.createLocalUser(creds, user.getPrincipal(), s2bb("unused")); // Login in as that user we just created UserGroupInformation.loginUserFromKeytab(user.getPrincipal(), user.getKeytab().getAbsolutePath()); final UserGroupInformation badUgi = UserGroupInformation.getCurrentUser(); // Get a "Credentials" object for the proxy TestProxyClient badClient = new TestProxyClient(hostname, proxyPort, factory, proxyPrimary, badUgi); try { Client badProxy = badClient.proxy(); badLogin = badProxy.login(user.getPrincipal(), properties); } finally { badClient.close(); } // Log back in as the test user UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); // Drop test user, invalidating the credentials (not to mention not having the krb credentials anymore) client.dropLocalUser(creds, user.getPrincipal()); } else { proxyClient = new TestProxyClient(hostname, proxyPort, factory); client = proxyClient.proxy(); creds = client.login("root", properties); // Create 'user' client.createLocalUser(creds, "user", s2bb(SharedMiniClusterBase.getRootPassword())); // Log in as 'user' badLogin = client.login("user", properties); // Drop 'user', invalidating the credentials client.dropLocalUser(creds, "user"); } // Create some unique names for tables, namespaces, etc. String[] uniqueNames = getUniqueNames(2); // Create a general table to be used tableName = uniqueNames[0]; client.createTable(creds, tableName, true, TimeType.MILLIS); // Create a general namespace to be used namespaceName = uniqueNames[1]; client.createNamespace(creds, namespaceName); } @After public void teardown() throws Exception { if (null != tableName) { if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); } try { if (client.tableExists(creds, tableName)) { client.deleteTable(creds, tableName); } } catch (Exception e) { log.warn("Failed to delete test table", e); } } if (null != namespaceName) { try { if (client.namespaceExists(creds, namespaceName)) { client.deleteNamespace(creds, namespaceName); } } catch (Exception e) { log.warn("Failed to delete test namespace", e); } } // Close the transport after the test if (null != proxyClient) { proxyClient.close(); } } /* * Set a lower timeout for tests that should fail fast */ @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void addConstraintLoginFailure() throws Exception { client.addConstraint(badLogin, tableName, NumericValueConstraint.class.getName()); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void addSplitsLoginFailure() throws Exception { client.addSplits(badLogin, tableName, Collections.singleton(s2bb("1"))); } @Test(expected = TApplicationException.class, timeout = 5000) public void clearLocatorCacheLoginFailure() throws Exception { client.clearLocatorCache(badLogin, tableName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void compactTableLoginFailure() throws Exception { client.compactTable(badLogin, tableName, null, null, null, true, false, null); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void cancelCompactionLoginFailure() throws Exception { client.cancelCompaction(badLogin, tableName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void createTableLoginFailure() throws Exception { client.createTable(badLogin, tableName, false, TimeType.MILLIS); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void deleteTableLoginFailure() throws Exception { client.deleteTable(badLogin, tableName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void deleteRowsLoginFailure() throws Exception { client.deleteRows(badLogin, tableName, null, null); } @Test(expected = TApplicationException.class, timeout = 5000) public void tableExistsLoginFailure() throws Exception { client.tableExists(badLogin, tableName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void flustTableLoginFailure() throws Exception { client.flushTable(badLogin, tableName, null, null, false); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getLocalityGroupsLoginFailure() throws Exception { client.getLocalityGroups(badLogin, tableName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getMaxRowLoginFailure() throws Exception { client.getMaxRow(badLogin, tableName, Collections.<ByteBuffer>emptySet(), null, false, null, false); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getTablePropertiesLoginFailure() throws Exception { client.getTableProperties(badLogin, tableName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void listSplitsLoginFailure() throws Exception { client.listSplits(badLogin, tableName, 10000); } @Test(expected = TApplicationException.class, timeout = 5000) public void listTablesLoginFailure() throws Exception { client.listTables(badLogin); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void listConstraintsLoginFailure() throws Exception { client.listConstraints(badLogin, tableName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void mergeTabletsLoginFailure() throws Exception { client.mergeTablets(badLogin, tableName, null, null); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void offlineTableLoginFailure() throws Exception { client.offlineTable(badLogin, tableName, false); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void onlineTableLoginFailure() throws Exception { client.onlineTable(badLogin, tableName, false); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void removeConstraintLoginFailure() throws Exception { client.removeConstraint(badLogin, tableName, 0); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void removeTablePropertyLoginFailure() throws Exception { client.removeTableProperty(badLogin, tableName, Property.TABLE_FILE_MAX.getKey()); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void renameTableLoginFailure() throws Exception { client.renameTable(badLogin, tableName, "someTableName"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void setLocalityGroupsLoginFailure() throws Exception { Map<String, Set<String>> groups = new HashMap<String, Set<String>>(); groups.put("group1", Collections.singleton("cf1")); groups.put("group2", Collections.singleton("cf2")); client.setLocalityGroups(badLogin, tableName, groups); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void setTablePropertyLoginFailure() throws Exception { client.setTableProperty(badLogin, tableName, Property.TABLE_FILE_MAX.getKey(), "0"); } @Test(expected = TException.class, timeout = 5000) public void tableIdMapLoginFailure() throws Exception { client.tableIdMap(badLogin); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getSiteConfigurationLoginFailure() throws Exception { client.getSiteConfiguration(badLogin); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getSystemConfigurationLoginFailure() throws Exception { client.getSystemConfiguration(badLogin); } @Test(expected = TException.class, timeout = 5000) public void getTabletServersLoginFailure() throws Exception { client.getTabletServers(badLogin); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getActiveScansLoginFailure() throws Exception { client.getActiveScans(badLogin, "fake"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getActiveCompactionsLoginFailure() throws Exception { client.getActiveCompactions(badLogin, "fakse"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void removePropertyLoginFailure() throws Exception { client.removeProperty(badLogin, "table.split.threshold"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void setPropertyLoginFailure() throws Exception { client.setProperty(badLogin, "table.split.threshold", "500M"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void testClassLoadLoginFailure() throws Exception { client.testClassLoad(badLogin, DevNull.class.getName(), SortedKeyValueIterator.class.getName()); } @Test(timeout = 5000) public void authenticateUserLoginFailure() throws Exception { if (!isKerberosEnabled()) { try { // Not really a relevant test for kerberos client.authenticateUser(badLogin, "root", s2pp(SharedMiniClusterBase.getRootPassword())); fail("Expected AccumuloSecurityException"); } catch (AccumuloSecurityException e) { // Expected return; } } } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void changeUserAuthorizationsLoginFailure() throws Exception { HashSet<ByteBuffer> auths = new HashSet<ByteBuffer>(Arrays.asList(s2bb("A"), s2bb("B"))); client.changeUserAuthorizations(badLogin, "stooge", auths); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void changePasswordLoginFailure() throws Exception { client.changeLocalUserPassword(badLogin, "stooge", s2bb("")); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void createUserLoginFailure() throws Exception { client.createLocalUser(badLogin, "stooge", s2bb("password")); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void dropUserLoginFailure() throws Exception { client.dropLocalUser(badLogin, "stooge"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getUserAuthorizationsLoginFailure() throws Exception { client.getUserAuthorizations(badLogin, "stooge"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void grantSystemPermissionLoginFailure() throws Exception { client.grantSystemPermission(badLogin, "stooge", SystemPermission.CREATE_TABLE); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void grantTablePermissionLoginFailure() throws Exception { client.grantTablePermission(badLogin, "root", tableName, TablePermission.WRITE); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void hasSystemPermissionLoginFailure() throws Exception { client.hasSystemPermission(badLogin, "stooge", SystemPermission.CREATE_TABLE); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void hasTablePermission() throws Exception { client.hasTablePermission(badLogin, "root", tableName, TablePermission.WRITE); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void listLocalUsersLoginFailure() throws Exception { client.listLocalUsers(badLogin); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void revokeSystemPermissionLoginFailure() throws Exception { client.revokeSystemPermission(badLogin, "stooge", SystemPermission.CREATE_TABLE); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void revokeTablePermissionLoginFailure() throws Exception { client.revokeTablePermission(badLogin, "root", tableName, TablePermission.ALTER_TABLE); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void createScannerLoginFailure() throws Exception { client.createScanner(badLogin, tableName, new ScanOptions()); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void createBatchScannerLoginFailure() throws Exception { client.createBatchScanner(badLogin, tableName, new BatchScanOptions()); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void updateAndFlushLoginFailure() throws Exception { client.updateAndFlush(badLogin, tableName, new HashMap<ByteBuffer, List<ColumnUpdate>>()); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void createWriterLoginFailure() throws Exception { client.createWriter(badLogin, tableName, new WriterOptions()); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void attachIteratorLoginFailure() throws Exception { client.attachIterator(badLogin, "slow", setting, EnumSet.allOf(IteratorScope.class)); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void checkIteratorLoginFailure() throws Exception { client.checkIteratorConflicts(badLogin, tableName, setting, EnumSet.allOf(IteratorScope.class)); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void cloneTableLoginFailure() throws Exception { client.cloneTable(badLogin, tableName, tableName + "_clone", false, null, null); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void exportTableLoginFailure() throws Exception { client.exportTable(badLogin, tableName, "/tmp"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void importTableLoginFailure() throws Exception { client.importTable(badLogin, "testify", "/tmp"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getIteratorSettingLoginFailure() throws Exception { client.getIteratorSetting(badLogin, tableName, "foo", IteratorScope.SCAN); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void listIteratorsLoginFailure() throws Exception { client.listIterators(badLogin, tableName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void removeIteratorLoginFailure() throws Exception { client.removeIterator(badLogin, tableName, "name", EnumSet.allOf(IteratorScope.class)); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void splitRangeByTabletsLoginFailure() throws Exception { client.splitRangeByTablets(badLogin, tableName, client.getRowRange(ByteBuffer.wrap("row".getBytes(UTF_8))), 10); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void importDirectoryLoginFailure() throws Exception { MiniAccumuloClusterImpl cluster = SharedMiniClusterBase.getCluster(); Path base = cluster.getTemporaryPath(); Path importDir = new Path(base, "importDir"); Path failuresDir = new Path(base, "failuresDir"); assertTrue(cluster.getFileSystem().mkdirs(importDir)); assertTrue(cluster.getFileSystem().mkdirs(failuresDir)); client.importDirectory(badLogin, tableName, importDir.toString(), failuresDir.toString(), true); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void pingTabletServerLoginFailure() throws Exception { client.pingTabletServer(badLogin, "fake"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void loginFailure() throws Exception { client.login("badUser", properties); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void testTableClassLoadLoginFailure() throws Exception { client.testTableClassLoad(badLogin, tableName, VersioningIterator.class.getName(), SortedKeyValueIterator.class.getName()); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void createConditionalWriterLoginFailure() throws Exception { client.createConditionalWriter(badLogin, tableName, new ConditionalWriterOptions()); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void grantNamespacePermissionLoginFailure() throws Exception { client.grantNamespacePermission(badLogin, "stooge", namespaceName, NamespacePermission.ALTER_NAMESPACE); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void hasNamespacePermissionLoginFailure() throws Exception { client.hasNamespacePermission(badLogin, "stooge", namespaceName, NamespacePermission.ALTER_NAMESPACE); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void revokeNamespacePermissionLoginFailure() throws Exception { client.revokeNamespacePermission(badLogin, "stooge", namespaceName, NamespacePermission.ALTER_NAMESPACE); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void listNamespacesLoginFailure() throws Exception { client.listNamespaces(badLogin); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void namespaceExistsLoginFailure() throws Exception { client.namespaceExists(badLogin, namespaceName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void createNamespaceLoginFailure() throws Exception { client.createNamespace(badLogin, "abcdef"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void deleteNamespaceLoginFailure() throws Exception { client.deleteNamespace(badLogin, namespaceName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void renameNamespaceLoginFailure() throws Exception { client.renameNamespace(badLogin, namespaceName, "abcdef"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void setNamespacePropertyLoginFailure() throws Exception { client.setNamespaceProperty(badLogin, namespaceName, "table.compaction.major.ratio", "4"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void removeNamespacePropertyLoginFailure() throws Exception { client.removeNamespaceProperty(badLogin, namespaceName, "table.compaction.major.ratio"); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getNamespacePropertiesLoginFailure() throws Exception { client.getNamespaceProperties(badLogin, namespaceName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void namespaceIdMapLoginFailure() throws Exception { client.namespaceIdMap(badLogin); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void attachNamespaceIteratorLoginFailure() throws Exception { IteratorSetting setting = new IteratorSetting(100, "DebugTheThings", DebugIterator.class.getName(), Collections.<String, String>emptyMap()); client.attachNamespaceIterator(badLogin, namespaceName, setting, EnumSet.allOf(IteratorScope.class)); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void removeNamespaceIteratorLoginFailure() throws Exception { client.removeNamespaceIterator(badLogin, namespaceName, "DebugTheThings", EnumSet.allOf(IteratorScope.class)); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void getNamespaceIteratorSettingLoginFailure() throws Exception { client.getNamespaceIteratorSetting(badLogin, namespaceName, "DebugTheThings", IteratorScope.SCAN); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void listNamespaceIteratorsLoginFailure() throws Exception { client.listNamespaceIterators(badLogin, namespaceName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void checkNamespaceIteratorConflictsLoginFailure() throws Exception { IteratorSetting setting = new IteratorSetting(100, "DebugTheThings", DebugIterator.class.getName(), Collections.<String, String>emptyMap()); client.checkNamespaceIteratorConflicts(badLogin, namespaceName, setting, EnumSet.allOf(IteratorScope.class)); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void addNamespaceConstraintLoginFailure() throws Exception { client.addNamespaceConstraint(badLogin, namespaceName, MaxMutationSize.class.getName()); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void removeNamespaceConstraintLoginFailure() throws Exception { client.removeNamespaceConstraint(badLogin, namespaceName, 1); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void listNamespaceConstraintsLoginFailure() throws Exception { client.listNamespaceConstraints(badLogin, namespaceName); } @Test(expected = AccumuloSecurityException.class, timeout = 5000) public void testNamespaceClassLoadLoginFailure() throws Exception { client.testNamespaceClassLoad(badLogin, namespaceName, DebugIterator.class.getName(), SortedKeyValueIterator.class.getName()); } @Test public void tableNotFound() throws Exception { final String doesNotExist = "doesNotExists"; try { client.addConstraint(creds, doesNotExist, NumericValueConstraint.class.getName()); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.addSplits(creds, doesNotExist, Collections.<ByteBuffer>emptySet()); fail("exception not thrown"); } catch (TableNotFoundException ex) { } final IteratorSetting setting = new IteratorSetting(100, "slow", SlowIterator.class.getName(), Collections.singletonMap("sleepTime", "200")); try { client.attachIterator(creds, doesNotExist, setting, EnumSet.allOf(IteratorScope.class)); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.cancelCompaction(creds, doesNotExist); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.checkIteratorConflicts(creds, doesNotExist, setting, EnumSet.allOf(IteratorScope.class)); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.clearLocatorCache(creds, doesNotExist); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { final String TABLE_TEST = getUniqueNames(1)[0]; client.cloneTable(creds, doesNotExist, TABLE_TEST, false, null, null); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.compactTable(creds, doesNotExist, null, null, null, true, false, null); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.createBatchScanner(creds, doesNotExist, new BatchScanOptions()); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.createScanner(creds, doesNotExist, new ScanOptions()); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.createWriter(creds, doesNotExist, new WriterOptions()); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.deleteRows(creds, doesNotExist, null, null); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.deleteTable(creds, doesNotExist); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.exportTable(creds, doesNotExist, "/tmp"); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.flushTable(creds, doesNotExist, null, null, false); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.getIteratorSetting(creds, doesNotExist, "foo", IteratorScope.SCAN); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.getLocalityGroups(creds, doesNotExist); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.getMaxRow(creds, doesNotExist, Collections.<ByteBuffer>emptySet(), null, false, null, false); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.getTableProperties(creds, doesNotExist); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.grantTablePermission(creds, "root", doesNotExist, TablePermission.WRITE); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.hasTablePermission(creds, "root", doesNotExist, TablePermission.WRITE); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { MiniAccumuloClusterImpl cluster = SharedMiniClusterBase.getCluster(); Path base = cluster.getTemporaryPath(); Path importDir = new Path(base, "importDir"); Path failuresDir = new Path(base, "failuresDir"); assertTrue(cluster.getFileSystem().mkdirs(importDir)); assertTrue(cluster.getFileSystem().mkdirs(failuresDir)); client.importDirectory(creds, doesNotExist, importDir.toString(), failuresDir.toString(), true); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.listConstraints(creds, doesNotExist); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.listSplits(creds, doesNotExist, 10000); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.mergeTablets(creds, doesNotExist, null, null); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.offlineTable(creds, doesNotExist, false); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.onlineTable(creds, doesNotExist, false); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.removeConstraint(creds, doesNotExist, 0); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.removeIterator(creds, doesNotExist, "name", EnumSet.allOf(IteratorScope.class)); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.removeTableProperty(creds, doesNotExist, Property.TABLE_FILE_MAX.getKey()); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.renameTable(creds, doesNotExist, "someTableName"); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.revokeTablePermission(creds, "root", doesNotExist, TablePermission.ALTER_TABLE); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.setTableProperty(creds, doesNotExist, Property.TABLE_FILE_MAX.getKey(), "0"); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.splitRangeByTablets(creds, doesNotExist, client.getRowRange(ByteBuffer.wrap("row".getBytes(UTF_8))), 10); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.updateAndFlush(creds, doesNotExist, new HashMap<ByteBuffer, List<ColumnUpdate>>()); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.getDiskUsage(creds, Collections.singleton(doesNotExist)); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.testTableClassLoad(creds, doesNotExist, VersioningIterator.class.getName(), SortedKeyValueIterator.class.getName()); fail("exception not thrown"); } catch (TableNotFoundException ex) { } try { client.createConditionalWriter(creds, doesNotExist, new ConditionalWriterOptions()); fail("exception not thrown"); } catch (TableNotFoundException ex) { } } @Test public void namespaceNotFound() throws Exception { final String doesNotExist = "doesNotExists"; try { client.deleteNamespace(creds, doesNotExist); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.renameNamespace(creds, doesNotExist, "abcdefg"); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.setNamespaceProperty(creds, doesNotExist, "table.compaction.major.ratio", "4"); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.removeNamespaceProperty(creds, doesNotExist, "table.compaction.major.ratio"); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.getNamespaceProperties(creds, doesNotExist); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { IteratorSetting setting = new IteratorSetting(100, "DebugTheThings", DebugIterator.class.getName(), Collections.<String, String>emptyMap()); client.attachNamespaceIterator(creds, doesNotExist, setting, EnumSet.allOf(IteratorScope.class)); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.removeNamespaceIterator(creds, doesNotExist, "DebugTheThings", EnumSet.allOf(IteratorScope.class)); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.getNamespaceIteratorSetting(creds, doesNotExist, "DebugTheThings", IteratorScope.SCAN); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.listNamespaceIterators(creds, doesNotExist); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { IteratorSetting setting = new IteratorSetting(100, "DebugTheThings", DebugIterator.class.getName(), Collections.<String, String>emptyMap()); client.checkNamespaceIteratorConflicts(creds, doesNotExist, setting, EnumSet.allOf(IteratorScope.class)); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.addNamespaceConstraint(creds, doesNotExist, MaxMutationSize.class.getName()); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.removeNamespaceConstraint(creds, doesNotExist, 1); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.listNamespaceConstraints(creds, doesNotExist); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } try { client.testNamespaceClassLoad(creds, doesNotExist, DebugIterator.class.getName(), SortedKeyValueIterator.class.getName()); fail("exception not thrown"); } catch (NamespaceNotFoundException ex) { } } @Test public void testExists() throws Exception { client.createTable(creds, "ett1", false, TimeType.MILLIS); client.createTable(creds, "ett2", false, TimeType.MILLIS); try { client.createTable(creds, "ett1", false, TimeType.MILLIS); fail("exception not thrown"); } catch (TableExistsException tee) { } try { client.renameTable(creds, "ett1", "ett2"); fail("exception not thrown"); } catch (TableExistsException tee) { } try { client.cloneTable(creds, "ett1", "ett2", false, new HashMap<String, String>(), new HashSet<String>()); fail("exception not thrown"); } catch (TableExistsException tee) { } } @Test public void testNamespaceExists() throws Exception { client.createNamespace(creds, "foobar"); try { client.createNamespace(creds, namespaceName); fail("exception not thrown"); } catch (NamespaceExistsException ex) { } try { client.renameNamespace(creds, "foobar", namespaceName); fail("exception not thrown"); } catch (NamespaceExistsException ex) { } } @Test(expected = NamespaceNotEmptyException.class) public void testNamespaceNotEmpty() throws Exception { client.createTable(creds, namespaceName + ".abcdefg", true, TimeType.MILLIS); client.deleteNamespace(creds, namespaceName); } @Test public void testUnknownScanner() throws Exception { String scanner = client.createScanner(creds, tableName, null); assertFalse(client.hasNext(scanner)); client.closeScanner(scanner); try { client.hasNext(scanner); fail("exception not thrown"); } catch (UnknownScanner us) { } try { client.closeScanner(scanner); fail("exception not thrown"); } catch (UnknownScanner us) { } try { client.nextEntry("99999999"); fail("exception not thrown"); } catch (UnknownScanner us) { } try { client.nextK("99999999", 6); fail("exception not thrown"); } catch (UnknownScanner us) { } try { client.hasNext("99999999"); fail("exception not thrown"); } catch (UnknownScanner us) { } try { client.hasNext(UUID.randomUUID().toString()); fail("exception not thrown"); } catch (UnknownScanner us) { } } @Test public void testUnknownWriter() throws Exception { String writer = client.createWriter(creds, tableName, null); client.update(writer, mutation("row0", "cf", "cq", "value")); client.flush(writer); client.update(writer, mutation("row2", "cf", "cq", "value2")); client.closeWriter(writer); // this is a oneway call, so it does not throw exceptions client.update(writer, mutation("row2", "cf", "cq", "value2")); try { client.flush(writer); fail("exception not thrown"); } catch (UnknownWriter uw) { } try { client.flush("99999"); fail("exception not thrown"); } catch (UnknownWriter uw) { } try { client.flush(UUID.randomUUID().toString()); fail("exception not thrown"); } catch (UnknownWriter uw) { } try { client.closeWriter("99999"); fail("exception not thrown"); } catch (UnknownWriter uw) { } } @Test public void testDelete() throws Exception { client.updateAndFlush(creds, tableName, mutation("row0", "cf", "cq", "value")); assertScan(new String[][] { { "row0", "cf", "cq", "value" } }, tableName); ColumnUpdate upd = new ColumnUpdate(s2bb("cf"), s2bb("cq")); upd.setDeleteCell(false); Map<ByteBuffer, List<ColumnUpdate>> notDelete = Collections.singletonMap(s2bb("row0"), Collections.singletonList(upd)); client.updateAndFlush(creds, tableName, notDelete); String scanner = client.createScanner(creds, tableName, null); ScanResult entries = client.nextK(scanner, 10); client.closeScanner(scanner); assertFalse(entries.more); assertEquals("Results: " + entries.results, 1, entries.results.size()); upd = new ColumnUpdate(s2bb("cf"), s2bb("cq")); upd.setDeleteCell(true); Map<ByteBuffer, List<ColumnUpdate>> delete = Collections.singletonMap(s2bb("row0"), Collections.singletonList(upd)); client.updateAndFlush(creds, tableName, delete); assertScan(new String[][] {}, tableName); } @Test public void testSystemProperties() throws Exception { Map<String, String> cfg = client.getSiteConfiguration(creds); // set a property in zookeeper client.setProperty(creds, "table.split.threshold", "500M"); // check that we can read it for (int i = 0; i < 5; i++) { cfg = client.getSystemConfiguration(creds); if ("500M".equals(cfg.get("table.split.threshold"))) break; sleepUninterruptibly(200, TimeUnit.MILLISECONDS); } assertEquals("500M", cfg.get("table.split.threshold")); // unset the setting, check that it's not what it was client.removeProperty(creds, "table.split.threshold"); for (int i = 0; i < 5; i++) { cfg = client.getSystemConfiguration(creds); if (!"500M".equals(cfg.get("table.split.threshold"))) break; sleepUninterruptibly(200, TimeUnit.MILLISECONDS); } assertNotEquals("500M", cfg.get("table.split.threshold")); } @Test public void pingTabletServers() throws Exception { int tservers = 0; for (String tserver : client.getTabletServers(creds)) { client.pingTabletServer(creds, tserver); tservers++; } assertTrue(tservers > 0); } @Test public void testSiteConfiguration() throws Exception { // get something we know is in the site config MiniAccumuloClusterImpl cluster = SharedMiniClusterBase.getCluster(); Map<String, String> cfg = client.getSiteConfiguration(creds); assertTrue(cfg.get("instance.dfs.dir").startsWith(cluster.getConfig().getAccumuloDir().getAbsolutePath())); } @Test public void testClassLoad() throws Exception { // try to load some classes via the proxy assertTrue(client.testClassLoad(creds, DevNull.class.getName(), SortedKeyValueIterator.class.getName())); assertFalse(client.testClassLoad(creds, "foo.bar", SortedKeyValueIterator.class.getName())); } @Test public void attachIteratorsWithScans() throws Exception { if (client.tableExists(creds, "slow")) { client.deleteTable(creds, "slow"); } // create a table that's very slow, so we can look for scans client.createTable(creds, "slow", true, TimeType.MILLIS); IteratorSetting setting = new IteratorSetting(100, "slow", SlowIterator.class.getName(), Collections.singletonMap("sleepTime", "250")); client.attachIterator(creds, "slow", setting, EnumSet.allOf(IteratorScope.class)); // Should take 10 seconds to read every record for (int i = 0; i < 40; i++) { client.updateAndFlush(creds, "slow", mutation("row" + i, "cf", "cq", "value")); } // scan Thread t = new Thread() { @Override public void run() { String scanner; TestProxyClient proxyClient2 = null; try { if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); proxyClient2 = new TestProxyClient(hostname, proxyPort, factory, proxyPrimary, UserGroupInformation.getCurrentUser()); } else { proxyClient2 = new TestProxyClient(hostname, proxyPort, factory); } Client client2 = proxyClient2.proxy(); scanner = client2.createScanner(creds, "slow", null); client2.nextK(scanner, 10); client2.closeScanner(scanner); } catch (Exception e) { throw new RuntimeException(e); } finally { if (null != proxyClient2) { proxyClient2.close(); } } } }; t.start(); // look for the scan many times List<ActiveScan> scans = new ArrayList<ActiveScan>(); for (int i = 0; i < 100 && scans.isEmpty(); i++) { for (String tserver : client.getTabletServers(creds)) { List<ActiveScan> scansForServer = client.getActiveScans(creds, tserver); for (ActiveScan scan : scansForServer) { if (clientPrincipal.equals(scan.getUser())) { scans.add(scan); } } if (!scans.isEmpty()) break; sleepUninterruptibly(100, TimeUnit.MILLISECONDS); } } t.join(); assertFalse("Expected to find scans, but found none", scans.isEmpty()); boolean found = false; Map<String, String> map = null; for (int i = 0; i < scans.size() && !found; i++) { ActiveScan scan = scans.get(i); if (clientPrincipal.equals(scan.getUser())) { assertTrue(ScanState.RUNNING.equals(scan.getState()) || ScanState.QUEUED.equals(scan.getState())); assertEquals(ScanType.SINGLE, scan.getType()); assertEquals("slow", scan.getTable()); map = client.tableIdMap(creds); assertEquals(map.get("slow"), scan.getExtent().tableId); assertTrue(scan.getExtent().endRow == null); assertTrue(scan.getExtent().prevEndRow == null); found = true; } } assertTrue("Could not find a scan against the 'slow' table", found); } @Test public void attachIteratorWithCompactions() throws Exception { if (client.tableExists(creds, "slow")) { client.deleteTable(creds, "slow"); } // create a table that's very slow, so we can look for compactions client.createTable(creds, "slow", true, TimeType.MILLIS); IteratorSetting setting = new IteratorSetting(100, "slow", SlowIterator.class.getName(), Collections.singletonMap("sleepTime", "250")); client.attachIterator(creds, "slow", setting, EnumSet.allOf(IteratorScope.class)); // Should take 10 seconds to read every record for (int i = 0; i < 40; i++) { client.updateAndFlush(creds, "slow", mutation("row" + i, "cf", "cq", "value")); } Map<String, String> map = client.tableIdMap(creds); // start a compaction Thread t = new Thread() { @Override public void run() { TestProxyClient proxyClient2 = null; try { if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); proxyClient2 = new TestProxyClient(hostname, proxyPort, factory, proxyPrimary, UserGroupInformation.getCurrentUser()); } else { proxyClient2 = new TestProxyClient(hostname, proxyPort, factory); } Client client2 = proxyClient2.proxy(); client2.compactTable(creds, "slow", null, null, null, true, true, null); } catch (Exception e) { throw new RuntimeException(e); } finally { if (null != proxyClient2) { proxyClient2.close(); } } } }; t.start(); final String desiredTableId = map.get("slow"); // Make sure we can find the slow table assertNotNull(desiredTableId); // try to catch it in the act List<ActiveCompaction> compactions = new ArrayList<ActiveCompaction>(); for (int i = 0; i < 100 && compactions.isEmpty(); i++) { // Iterate over the tservers for (String tserver : client.getTabletServers(creds)) { // And get the compactions on each List<ActiveCompaction> compactionsOnServer = client.getActiveCompactions(creds, tserver); for (ActiveCompaction compact : compactionsOnServer) { // There might be other compactions occurring (e.g. on METADATA) in which // case we want to prune out those that aren't for our slow table if (desiredTableId.equals(compact.getExtent().tableId)) { compactions.add(compact); } } // If we found a compaction for the table we wanted, so we can stop looking if (!compactions.isEmpty()) break; } sleepUninterruptibly(10, TimeUnit.MILLISECONDS); } t.join(); // verify the compaction information assertFalse(compactions.isEmpty()); for (ActiveCompaction c : compactions) { if (desiredTableId.equals(c.getExtent().tableId)) { assertTrue(c.inputFiles.isEmpty()); assertEquals(CompactionType.MINOR, c.getType()); assertEquals(CompactionReason.USER, c.getReason()); assertEquals("", c.localityGroup); assertTrue(c.outputFile.contains("default_tablet")); return; } } fail("Expection to find running compaction for table 'slow' but did not find one"); } @Test public void userAuthentication() throws Exception { if (isKerberosEnabled()) { assertTrue(client.authenticateUser(creds, clientPrincipal, Collections.<String, String>emptyMap())); // Can't really authenticate "badly" at the application level w/ kerberos. It's going to fail to even set up // an RPC } else { // check password assertTrue(client.authenticateUser(creds, "root", s2pp(SharedMiniClusterBase.getRootPassword()))); assertFalse(client.authenticateUser(creds, "root", s2pp(""))); } } @Test public void userManagement() throws Exception { String user; ClusterUser otherClient = null; ByteBuffer password = s2bb("password"); if (isKerberosEnabled()) { otherClient = getKdc().getClientPrincipal(1); user = otherClient.getPrincipal(); } else { user = getUniqueNames(1)[0]; } // create a user client.createLocalUser(creds, user, password); // change auths Set<String> users = client.listLocalUsers(creds); Set<String> expectedUsers = new HashSet<String>(Arrays.asList(clientPrincipal, user)); assertTrue("Did not find all expected users: " + expectedUsers, users.containsAll(expectedUsers)); HashSet<ByteBuffer> auths = new HashSet<ByteBuffer>(Arrays.asList(s2bb("A"), s2bb("B"))); client.changeUserAuthorizations(creds, user, auths); List<ByteBuffer> update = client.getUserAuthorizations(creds, user); assertEquals(auths, new HashSet<ByteBuffer>(update)); // change password if (!isKerberosEnabled()) { password = s2bb(""); client.changeLocalUserPassword(creds, user, password); assertTrue(client.authenticateUser(creds, user, s2pp(ByteBufferUtil.toString(password)))); } if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); final UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); // Re-login in and make a new connection. Can't use the previous one TestProxyClient otherProxyClient = null; try { otherProxyClient = new TestProxyClient(hostname, proxyPort, factory, proxyPrimary, ugi); otherProxyClient.proxy().login(user, Collections.<String, String>emptyMap()); } finally { if (null != otherProxyClient) { otherProxyClient.close(); } } } else { // check login with new password client.login(user, s2pp(ByteBufferUtil.toString(password))); } } @Test public void userPermissions() throws Exception { String userName = getUniqueNames(1)[0]; ClusterUser otherClient = null; ByteBuffer password = s2bb("password"); ByteBuffer user; TestProxyClient origProxyClient = null; Client origClient = null; TestProxyClient userProxyClient = null; Client userClient = null; if (isKerberosEnabled()) { otherClient = getKdc().getClientPrincipal(1); userName = otherClient.getPrincipal(); UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); final UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); // Re-login in and make a new connection. Can't use the previous one userProxyClient = new TestProxyClient(hostname, proxyPort, factory, proxyPrimary, ugi); origProxyClient = proxyClient; origClient = client; userClient = client = userProxyClient.proxy(); user = client.login(userName, Collections.<String, String>emptyMap()); } else { userName = getUniqueNames(1)[0]; // create a user client.createLocalUser(creds, userName, password); user = client.login(userName, s2pp(ByteBufferUtil.toString(password))); } // check permission failure try { client.createTable(user, "fail", true, TimeType.MILLIS); fail("should not create the table"); } catch (AccumuloSecurityException ex) { if (isKerberosEnabled()) { // Switch back to original client UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } assertFalse(client.listTables(creds).contains("fail")); } // grant permissions and test assertFalse(client.hasSystemPermission(creds, userName, SystemPermission.CREATE_TABLE)); client.grantSystemPermission(creds, userName, SystemPermission.CREATE_TABLE); assertTrue(client.hasSystemPermission(creds, userName, SystemPermission.CREATE_TABLE)); if (isKerberosEnabled()) { // Switch back to the extra user UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); client = userClient; } client.createTable(user, "success", true, TimeType.MILLIS); if (isKerberosEnabled()) { // Switch back to original client UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } assertTrue(client.listTables(creds).contains("success")); // revoke permissions client.revokeSystemPermission(creds, userName, SystemPermission.CREATE_TABLE); assertFalse(client.hasSystemPermission(creds, userName, SystemPermission.CREATE_TABLE)); try { if (isKerberosEnabled()) { // Switch back to the extra user UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); client = userClient; } client.createTable(user, "fail", true, TimeType.MILLIS); fail("should not create the table"); } catch (AccumuloSecurityException ex) { if (isKerberosEnabled()) { // Switch back to original client UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } assertFalse(client.listTables(creds).contains("fail")); } // denied! try { if (isKerberosEnabled()) { // Switch back to the extra user UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); client = userClient; } String scanner = client.createScanner(user, tableName, null); client.nextK(scanner, 100); fail("stooge should not read table test"); } catch (AccumuloSecurityException ex) { } if (isKerberosEnabled()) { // Switch back to original client UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } // grant assertFalse(client.hasTablePermission(creds, userName, tableName, TablePermission.READ)); client.grantTablePermission(creds, userName, tableName, TablePermission.READ); assertTrue(client.hasTablePermission(creds, userName, tableName, TablePermission.READ)); if (isKerberosEnabled()) { // Switch back to the extra user UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); client = userClient; } String scanner = client.createScanner(user, tableName, null); client.nextK(scanner, 10); client.closeScanner(scanner); if (isKerberosEnabled()) { // Switch back to original client UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } // revoke client.revokeTablePermission(creds, userName, tableName, TablePermission.READ); assertFalse(client.hasTablePermission(creds, userName, tableName, TablePermission.READ)); try { if (isKerberosEnabled()) { // Switch back to the extra user UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); client = userClient; } scanner = client.createScanner(user, tableName, null); client.nextK(scanner, 100); fail("stooge should not read table test"); } catch (AccumuloSecurityException ex) { } if (isKerberosEnabled()) { // Switch back to original client UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } // delete user client.dropLocalUser(creds, userName); Set<String> users = client.listLocalUsers(creds); assertFalse("Should not see user after they are deleted", users.contains(userName)); if (isKerberosEnabled()) { userProxyClient.close(); proxyClient = origProxyClient; client = origClient; } } @Test public void namespacePermissions() throws Exception { String userName; ClusterUser otherClient = null; ByteBuffer password = s2bb("password"); ByteBuffer user; TestProxyClient origProxyClient = null; Client origClient = null; TestProxyClient userProxyClient = null; Client userClient = null; if (isKerberosEnabled()) { otherClient = getKdc().getClientPrincipal(1); userName = otherClient.getPrincipal(); UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); final UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); // Re-login in and make a new connection. Can't use the previous one userProxyClient = new TestProxyClient(hostname, proxyPort, factory, proxyPrimary, ugi); origProxyClient = proxyClient; origClient = client; userClient = client = userProxyClient.proxy(); user = client.login(userName, Collections.<String, String>emptyMap()); } else { userName = getUniqueNames(1)[0]; // create a user client.createLocalUser(creds, userName, password); user = client.login(userName, s2pp(ByteBufferUtil.toString(password))); } // check permission failure try { client.createTable(user, namespaceName + ".fail", true, TimeType.MILLIS); fail("should not create the table"); } catch (AccumuloSecurityException ex) { if (isKerberosEnabled()) { // Switch back to original client UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } assertFalse(client.listTables(creds).contains(namespaceName + ".fail")); } // grant permissions and test assertFalse( client.hasNamespacePermission(creds, userName, namespaceName, NamespacePermission.CREATE_TABLE)); client.grantNamespacePermission(creds, userName, namespaceName, NamespacePermission.CREATE_TABLE); assertTrue(client.hasNamespacePermission(creds, userName, namespaceName, NamespacePermission.CREATE_TABLE)); if (isKerberosEnabled()) { // Switch back to the extra user UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); client = userClient; } client.createTable(user, namespaceName + ".success", true, TimeType.MILLIS); if (isKerberosEnabled()) { // Switch back to original client UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } assertTrue(client.listTables(creds).contains(namespaceName + ".success")); // revoke permissions client.revokeNamespacePermission(creds, userName, namespaceName, NamespacePermission.CREATE_TABLE); assertFalse( client.hasNamespacePermission(creds, userName, namespaceName, NamespacePermission.CREATE_TABLE)); try { if (isKerberosEnabled()) { // Switch back to the extra user UserGroupInformation.loginUserFromKeytab(otherClient.getPrincipal(), otherClient.getKeytab().getAbsolutePath()); client = userClient; } client.createTable(user, namespaceName + ".fail", true, TimeType.MILLIS); fail("should not create the table"); } catch (AccumuloSecurityException ex) { if (isKerberosEnabled()) { // Switch back to original client UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } assertFalse(client.listTables(creds).contains(namespaceName + ".fail")); } // delete user client.dropLocalUser(creds, userName); Set<String> users = client.listLocalUsers(creds); assertFalse("Should not see user after they are deleted", users.contains(userName)); if (isKerberosEnabled()) { userProxyClient.close(); proxyClient = origProxyClient; client = origClient; } // delete table from namespace otherwise we can't delete namespace during teardown client.deleteTable(creds, namespaceName + ".success"); } @Test public void testBatchWriter() throws Exception { client.addConstraint(creds, tableName, NumericValueConstraint.class.getName()); // zookeeper propagation time sleepUninterruptibly(ZOOKEEPER_PROPAGATION_TIME, TimeUnit.MILLISECONDS); WriterOptions writerOptions = new WriterOptions(); writerOptions.setLatencyMs(10000); writerOptions.setMaxMemory(2); writerOptions.setThreads(1); writerOptions.setTimeoutMs(100000); Map<String, Integer> constraints = client.listConstraints(creds, tableName); while (!constraints.containsKey(NumericValueConstraint.class.getName())) { log.info("Constraints don't contain NumericValueConstraint"); Thread.sleep(2000); constraints = client.listConstraints(creds, tableName); } boolean success = false; for (int i = 0; i < 15; i++) { String batchWriter = client.createWriter(creds, tableName, writerOptions); client.update(batchWriter, mutation("row1", "cf", "cq", "x")); client.update(batchWriter, mutation("row1", "cf", "cq", "x")); try { client.flush(batchWriter); log.debug("Constraint failed to fire. Waiting and retrying"); Thread.sleep(5000); continue; } catch (MutationsRejectedException ex) { } try { client.closeWriter(batchWriter); log.debug("Constraint failed to fire. Waiting and retrying"); Thread.sleep(5000); continue; } catch (MutationsRejectedException e) { } success = true; break; } if (!success) { fail("constraint did not fire"); } client.removeConstraint(creds, tableName, 2); constraints = client.listConstraints(creds, tableName); while (constraints.containsKey(NumericValueConstraint.class.getName())) { log.info("Constraints still contains NumericValueConstraint"); Thread.sleep(2000); constraints = client.listConstraints(creds, tableName); } assertScan(new String[][] {}, tableName); sleepUninterruptibly(ZOOKEEPER_PROPAGATION_TIME, TimeUnit.MILLISECONDS); writerOptions = new WriterOptions(); writerOptions.setLatencyMs(10000); writerOptions.setMaxMemory(3000); writerOptions.setThreads(1); writerOptions.setTimeoutMs(100000); success = false; for (int i = 0; i < 15; i++) { try { String batchWriter = client.createWriter(creds, tableName, writerOptions); client.update(batchWriter, mutation("row1", "cf", "cq", "x")); client.flush(batchWriter); client.closeWriter(batchWriter); success = true; break; } catch (MutationsRejectedException e) { log.info("Mutations were rejected, assuming constraint is still active", e); Thread.sleep(5000); } } if (!success) { fail("Failed to successfully write data after constraint was removed"); } assertScan(new String[][] { { "row1", "cf", "cq", "x" } }, tableName); client.deleteTable(creds, tableName); } @Test public void testTableConstraints() throws Exception { log.debug("Setting NumericValueConstraint on " + tableName); // constraints client.addConstraint(creds, tableName, NumericValueConstraint.class.getName()); // zookeeper propagation time Thread.sleep(ZOOKEEPER_PROPAGATION_TIME); log.debug("Attempting to verify client-side that constraints are observed"); Map<String, Integer> constraints = client.listConstraints(creds, tableName); while (!constraints.containsKey(NumericValueConstraint.class.getName())) { log.debug("Constraints don't contain NumericValueConstraint"); Thread.sleep(2000); constraints = client.listConstraints(creds, tableName); } assertEquals(2, client.listConstraints(creds, tableName).size()); log.debug("Verified client-side that constraints exist"); // Write data that satisfies the constraint client.updateAndFlush(creds, tableName, mutation("row1", "cf", "cq", "123")); log.debug("Successfully wrote data that satisfies the constraint"); log.debug("Trying to write data that the constraint should reject"); // Expect failure on data that fails the constraint while (true) { try { client.updateAndFlush(creds, tableName, mutation("row1", "cf", "cq", "x")); log.debug("Expected mutation to be rejected, but was not. Waiting and retrying"); Thread.sleep(5000); } catch (MutationsRejectedException ex) { break; } } log.debug("Saw expected failure on data which fails the constraint"); log.debug("Removing constraint from table"); client.removeConstraint(creds, tableName, 2); sleepUninterruptibly(ZOOKEEPER_PROPAGATION_TIME, TimeUnit.MILLISECONDS); constraints = client.listConstraints(creds, tableName); while (constraints.containsKey(NumericValueConstraint.class.getName())) { log.debug("Constraints contains NumericValueConstraint"); Thread.sleep(2000); constraints = client.listConstraints(creds, tableName); } assertEquals(1, client.listConstraints(creds, tableName).size()); log.debug("Verified client-side that the constraint was removed"); log.debug("Attempting to write mutation that should succeed after constraints was removed"); // Make sure we can write the data after we removed the constraint while (true) { try { client.updateAndFlush(creds, tableName, mutation("row1", "cf", "cq", "x")); break; } catch (MutationsRejectedException ex) { log.debug("Expected mutation accepted, but was not. Waiting and retrying"); Thread.sleep(5000); } } log.debug("Verifying that record can be read from the table"); assertScan(new String[][] { { "row1", "cf", "cq", "x" } }, tableName); } @Test public void tableMergesAndSplits() throws Exception { // add some splits client.addSplits(creds, tableName, new HashSet<ByteBuffer>(Arrays.asList(s2bb("a"), s2bb("m"), s2bb("z")))); List<ByteBuffer> splits = client.listSplits(creds, tableName, 1); assertEquals(Arrays.asList(s2bb("m")), splits); // Merge some of the splits away client.mergeTablets(creds, tableName, null, s2bb("m")); splits = client.listSplits(creds, tableName, 10); assertEquals(Arrays.asList(s2bb("m"), s2bb("z")), splits); // Merge the entire table client.mergeTablets(creds, tableName, null, null); splits = client.listSplits(creds, tableName, 10); List<ByteBuffer> empty = Collections.emptyList(); // No splits after merge on whole table assertEquals(empty, splits); } @Test public void iteratorFunctionality() throws Exception { // iterators HashMap<String, String> options = new HashMap<String, String>(); options.put("type", "STRING"); options.put("columns", "cf"); IteratorSetting setting = new IteratorSetting(10, tableName, SummingCombiner.class.getName(), options); client.attachIterator(creds, tableName, setting, EnumSet.allOf(IteratorScope.class)); for (int i = 0; i < 10; i++) { client.updateAndFlush(creds, tableName, mutation("row1", "cf", "cq", "1")); } // 10 updates of "1" in the value w/ SummingCombiner should return value of "10" assertScan(new String[][] { { "row1", "cf", "cq", "10" } }, tableName); try { client.checkIteratorConflicts(creds, tableName, setting, EnumSet.allOf(IteratorScope.class)); fail("checkIteratorConflicts did not throw an exception"); } catch (Exception ex) { // Expected } client.deleteRows(creds, tableName, null, null); client.removeIterator(creds, tableName, "test", EnumSet.allOf(IteratorScope.class)); String expected[][] = new String[10][]; for (int i = 0; i < 10; i++) { client.updateAndFlush(creds, tableName, mutation("row" + i, "cf", "cq", "" + i)); expected[i] = new String[] { "row" + i, "cf", "cq", "" + i }; client.flushTable(creds, tableName, null, null, true); } assertScan(expected, tableName); } @Test public void cloneTable() throws Exception { String TABLE_TEST2 = getUniqueNames(2)[1]; String expected[][] = new String[10][]; for (int i = 0; i < 10; i++) { client.updateAndFlush(creds, tableName, mutation("row" + i, "cf", "cq", "" + i)); expected[i] = new String[] { "row" + i, "cf", "cq", "" + i }; client.flushTable(creds, tableName, null, null, true); } assertScan(expected, tableName); // clone client.cloneTable(creds, tableName, TABLE_TEST2, true, null, null); assertScan(expected, TABLE_TEST2); client.deleteTable(creds, TABLE_TEST2); } @Test public void clearLocatorCache() throws Exception { // don't know how to test this, call it just for fun client.clearLocatorCache(creds, tableName); } @Test public void compactTable() throws Exception { String expected[][] = new String[10][]; for (int i = 0; i < 10; i++) { client.updateAndFlush(creds, tableName, mutation("row" + i, "cf", "cq", "" + i)); expected[i] = new String[] { "row" + i, "cf", "cq", "" + i }; client.flushTable(creds, tableName, null, null, true); } assertScan(expected, tableName); // compact client.compactTable(creds, tableName, null, null, null, true, true, null); assertEquals(1, countFiles(tableName)); assertScan(expected, tableName); } @Test public void diskUsage() throws Exception { String TABLE_TEST2 = getUniqueNames(2)[1]; // Write some data String expected[][] = new String[10][]; for (int i = 0; i < 10; i++) { client.updateAndFlush(creds, tableName, mutation("row" + i, "cf", "cq", "" + i)); expected[i] = new String[] { "row" + i, "cf", "cq", "" + i }; client.flushTable(creds, tableName, null, null, true); } assertScan(expected, tableName); // compact client.compactTable(creds, tableName, null, null, null, true, true, null); assertEquals(1, countFiles(tableName)); assertScan(expected, tableName); // Clone the table client.cloneTable(creds, tableName, TABLE_TEST2, true, null, null); Set<String> tablesToScan = new HashSet<String>(); tablesToScan.add(tableName); tablesToScan.add(TABLE_TEST2); tablesToScan.add("foo"); client.createTable(creds, "foo", true, TimeType.MILLIS); // get disk usage List<DiskUsage> diskUsage = (client.getDiskUsage(creds, tablesToScan)); assertEquals(2, diskUsage.size()); // The original table and the clone are lumped together (they share the same files) assertEquals(2, diskUsage.get(0).getTables().size()); // The empty table we created assertEquals(1, diskUsage.get(1).getTables().size()); // Compact the clone so it writes its own files instead of referring to the original client.compactTable(creds, TABLE_TEST2, null, null, null, true, true, null); diskUsage = (client.getDiskUsage(creds, tablesToScan)); assertEquals(3, diskUsage.size()); // The original assertEquals(1, diskUsage.get(0).getTables().size()); // The clone w/ its own files now assertEquals(1, diskUsage.get(1).getTables().size()); // The empty table assertEquals(1, diskUsage.get(2).getTables().size()); client.deleteTable(creds, "foo"); client.deleteTable(creds, TABLE_TEST2); } @Test public void importExportTable() throws Exception { // Write some data String expected[][] = new String[10][]; for (int i = 0; i < 10; i++) { client.updateAndFlush(creds, tableName, mutation("row" + i, "cf", "cq", "" + i)); expected[i] = new String[] { "row" + i, "cf", "cq", "" + i }; client.flushTable(creds, tableName, null, null, true); } assertScan(expected, tableName); // export/import MiniAccumuloClusterImpl cluster = SharedMiniClusterBase.getCluster(); FileSystem fs = cluster.getFileSystem(); Path base = cluster.getTemporaryPath(); Path dir = new Path(base, "test"); assertTrue(fs.mkdirs(dir)); Path destDir = new Path(base, "test_dest"); assertTrue(fs.mkdirs(destDir)); client.offlineTable(creds, tableName, false); client.exportTable(creds, tableName, dir.toString()); // copy files to a new location FSDataInputStream is = fs.open(new Path(dir, "distcp.txt")); try (BufferedReader r = new BufferedReader(new InputStreamReader(is, UTF_8))) { while (true) { String line = r.readLine(); if (line == null) break; Path srcPath = new Path(line); FileUtil.copy(fs, srcPath, fs, destDir, false, fs.getConf()); } } client.deleteTable(creds, tableName); client.importTable(creds, "testify", destDir.toString()); assertScan(expected, "testify"); client.deleteTable(creds, "testify"); try { // ACCUMULO-1558 a second import from the same dir should fail, the first import moved the files client.importTable(creds, "testify2", destDir.toString()); fail(); } catch (Exception e) { } assertFalse(client.listTables(creds).contains("testify2")); } @Test public void localityGroups() throws Exception { Map<String, Set<String>> groups = new HashMap<String, Set<String>>(); groups.put("group1", Collections.singleton("cf1")); groups.put("group2", Collections.singleton("cf2")); client.setLocalityGroups(creds, tableName, groups); assertEquals(groups, client.getLocalityGroups(creds, tableName)); } @Test public void tableProperties() throws Exception { Map<String, String> systemProps = client.getSystemConfiguration(creds); String systemTableSplitThreshold = systemProps.get("table.split.threshold"); Map<String, String> orig = client.getTableProperties(creds, tableName); client.setTableProperty(creds, tableName, "table.split.threshold", "500M"); // Get the new table property value Map<String, String> update = client.getTableProperties(creds, tableName); assertEquals(update.get("table.split.threshold"), "500M"); // Table level properties shouldn't affect system level values assertEquals(systemTableSplitThreshold, client.getSystemConfiguration(creds).get("table.split.threshold")); client.removeTableProperty(creds, tableName, "table.split.threshold"); update = client.getTableProperties(creds, tableName); assertEquals(orig, update); } @Test public void tableRenames() throws Exception { // rename table Map<String, String> tables = client.tableIdMap(creds); client.renameTable(creds, tableName, "bar"); Map<String, String> tables2 = client.tableIdMap(creds); assertEquals(tables.get(tableName), tables2.get("bar")); // table exists assertTrue(client.tableExists(creds, "bar")); assertFalse(client.tableExists(creds, tableName)); client.renameTable(creds, "bar", tableName); } @Test public void bulkImport() throws Exception { MiniAccumuloClusterImpl cluster = SharedMiniClusterBase.getCluster(); FileSystem fs = cluster.getFileSystem(); Path base = cluster.getTemporaryPath(); Path dir = new Path(base, "test"); assertTrue(fs.mkdirs(dir)); // Write an RFile String filename = dir + "/bulk/import/rfile.rf"; FileSKVWriter writer = FileOperations.getInstance().newWriterBuilder().forFile(filename, fs, fs.getConf()) .withTableConfiguration(DefaultConfiguration.getInstance()).build(); writer.startDefaultLocalityGroup(); writer.append(new org.apache.accumulo.core.data.Key(new Text("a"), new Text("b"), new Text("c")), new Value("value".getBytes(UTF_8))); writer.close(); // Create failures directory fs.mkdirs(new Path(dir + "/bulk/fail")); // Run the bulk import client.importDirectory(creds, tableName, dir + "/bulk/import", dir + "/bulk/fail", true); // Make sure we find the data String scanner = client.createScanner(creds, tableName, null); ScanResult more = client.nextK(scanner, 100); client.closeScanner(scanner); assertEquals(1, more.results.size()); ByteBuffer maxRow = client.getMaxRow(creds, tableName, null, null, false, null, false); assertEquals(s2bb("a"), maxRow); } @Test public void testTableClassLoad() throws Exception { assertFalse(client.testTableClassLoad(creds, tableName, "abc123", SortedKeyValueIterator.class.getName())); assertTrue(client.testTableClassLoad(creds, tableName, VersioningIterator.class.getName(), SortedKeyValueIterator.class.getName())); } private Condition newCondition(String cf, String cq) { return new Condition(new Column(s2bb(cf), s2bb(cq), s2bb(""))); } private Condition newCondition(String cf, String cq, String val) { return newCondition(cf, cq).setValue(s2bb(val)); } private Condition newCondition(String cf, String cq, long ts, String val) { return newCondition(cf, cq).setValue(s2bb(val)).setTimestamp(ts); } private ColumnUpdate newColUpdate(String cf, String cq, String val) { return new ColumnUpdate(s2bb(cf), s2bb(cq)).setValue(s2bb(val)); } private ColumnUpdate newColUpdate(String cf, String cq, long ts, String val) { return new ColumnUpdate(s2bb(cf), s2bb(cq)).setTimestamp(ts).setValue(s2bb(val)); } private void assertScan(String[][] expected, String table) throws Exception { String scid = client.createScanner(creds, table, new ScanOptions()); ScanResult keyValues = client.nextK(scid, expected.length + 1); assertEquals("Saw " + keyValues.results, expected.length, keyValues.results.size()); assertFalse(keyValues.more); for (int i = 0; i < keyValues.results.size(); i++) { checkKey(expected[i][0], expected[i][1], expected[i][2], expected[i][3], keyValues.results.get(i)); } client.closeScanner(scid); } @Test public void testConditionalWriter() throws Exception { log.debug("Adding constraint {} to {}", tableName, NumericValueConstraint.class.getName()); client.addConstraint(creds, tableName, NumericValueConstraint.class.getName()); sleepUninterruptibly(ZOOKEEPER_PROPAGATION_TIME, TimeUnit.MILLISECONDS); while (!client.listConstraints(creds, tableName).containsKey(NumericValueConstraint.class.getName())) { log.info("Failed to see constraint"); Thread.sleep(1000); } String cwid = client.createConditionalWriter(creds, tableName, new ConditionalWriterOptions()); Map<ByteBuffer, ConditionalUpdates> updates = new HashMap<ByteBuffer, ConditionalUpdates>(); updates.put(s2bb("00345"), new ConditionalUpdates(Arrays.asList(newCondition("meta", "seq")), Arrays.asList(newColUpdate("meta", "seq", 10, "1"), newColUpdate("data", "img", "73435435")))); Map<ByteBuffer, ConditionalStatus> results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.ACCEPTED, results.get(s2bb("00345"))); assertScan(new String[][] { { "00345", "data", "img", "73435435" }, { "00345", "meta", "seq", "1" } }, tableName); // test not setting values on conditions updates.clear(); updates.put(s2bb("00345"), new ConditionalUpdates(Arrays.asList(newCondition("meta", "seq")), Arrays.asList(newColUpdate("meta", "seq", "2")))); updates.put(s2bb("00346"), new ConditionalUpdates(Arrays.asList(newCondition("meta", "seq")), Arrays.asList(newColUpdate("meta", "seq", "1")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(2, results.size()); assertEquals(ConditionalStatus.REJECTED, results.get(s2bb("00345"))); assertEquals(ConditionalStatus.ACCEPTED, results.get(s2bb("00346"))); assertScan(new String[][] { { "00345", "data", "img", "73435435" }, { "00345", "meta", "seq", "1" }, { "00346", "meta", "seq", "1" } }, tableName); // test setting values on conditions updates.clear(); updates.put(s2bb("00345"), new ConditionalUpdates(Arrays.asList(newCondition("meta", "seq", "1")), Arrays.asList(newColUpdate("meta", "seq", 20, "2"), newColUpdate("data", "img", "567890")))); updates.put(s2bb("00346"), new ConditionalUpdates(Arrays.asList(newCondition("meta", "seq", "2")), Arrays.asList(newColUpdate("meta", "seq", "3")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(2, results.size()); assertEquals(ConditionalStatus.ACCEPTED, results.get(s2bb("00345"))); assertEquals(ConditionalStatus.REJECTED, results.get(s2bb("00346"))); assertScan(new String[][] { { "00345", "data", "img", "567890" }, { "00345", "meta", "seq", "2" }, { "00346", "meta", "seq", "1" } }, tableName); // test setting timestamp on condition to a non-existant version updates.clear(); updates.put(s2bb("00345"), new ConditionalUpdates(Arrays.asList(newCondition("meta", "seq", 10, "2")), Arrays.asList(newColUpdate("meta", "seq", 30, "3"), newColUpdate("data", "img", "1234567890")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.REJECTED, results.get(s2bb("00345"))); assertScan(new String[][] { { "00345", "data", "img", "567890" }, { "00345", "meta", "seq", "2" }, { "00346", "meta", "seq", "1" } }, tableName); // test setting timestamp to an existing version updates.clear(); updates.put(s2bb("00345"), new ConditionalUpdates(Arrays.asList(newCondition("meta", "seq", 20, "2")), Arrays.asList(newColUpdate("meta", "seq", 30, "3"), newColUpdate("data", "img", "1234567890")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.ACCEPTED, results.get(s2bb("00345"))); assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" } }, tableName); // run test w/ condition that has iterators // following should fail w/o iterator client.updateAndFlush(creds, tableName, Collections.singletonMap(s2bb("00347"), Arrays.asList(newColUpdate("data", "count", "1")))); client.updateAndFlush(creds, tableName, Collections.singletonMap(s2bb("00347"), Arrays.asList(newColUpdate("data", "count", "1")))); client.updateAndFlush(creds, tableName, Collections.singletonMap(s2bb("00347"), Arrays.asList(newColUpdate("data", "count", "1")))); updates.clear(); updates.put(s2bb("00347"), new ConditionalUpdates(Arrays.asList(newCondition("data", "count", "3")), Arrays.asList(newColUpdate("data", "img", "1234567890")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.REJECTED, results.get(s2bb("00347"))); assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "1" } }, tableName); // following test w/ iterator setup should succeed Condition iterCond = newCondition("data", "count", "3"); Map<String, String> props = new HashMap<String, String>(); props.put("type", "STRING"); props.put("columns", "data:count"); IteratorSetting is = new IteratorSetting(1, "sumc", SummingCombiner.class.getName(), props); iterCond.setIterators(Arrays.asList(is)); updates.clear(); updates.put(s2bb("00347"), new ConditionalUpdates(Arrays.asList(iterCond), Arrays.asList(newColUpdate("data", "img", "1234567890")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.ACCEPTED, results.get(s2bb("00347"))); assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "1" }, { "00347", "data", "img", "1234567890" } }, tableName); ConditionalStatus status = null; for (int i = 0; i < 30; i++) { // test a mutation that violated a constraint updates.clear(); updates.put(s2bb("00347"), new ConditionalUpdates(Arrays.asList(newCondition("data", "img", "1234567890")), Arrays.asList(newColUpdate("data", "count", "A")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); status = results.get(s2bb("00347")); if (ConditionalStatus.VIOLATED != status) { log.info( "ConditionalUpdate was not rejected by server due to table constraint. Sleeping and retrying"); Thread.sleep(5000); continue; } assertEquals(ConditionalStatus.VIOLATED, status); break; } // Final check to make sure we succeeded and didn't exceed the retries assertEquals(ConditionalStatus.VIOLATED, status); assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "1" }, { "00347", "data", "img", "1234567890" } }, tableName); // run test with two conditions // both conditions should fail updates.clear(); updates.put(s2bb("00347"), new ConditionalUpdates( Arrays.asList(newCondition("data", "img", "565"), newCondition("data", "count", "2")), Arrays.asList(newColUpdate("data", "count", "3"), newColUpdate("data", "img", "0987654321")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.REJECTED, results.get(s2bb("00347"))); assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "1" }, { "00347", "data", "img", "1234567890" } }, tableName); // one condition should fail updates.clear(); updates.put(s2bb("00347"), new ConditionalUpdates( Arrays.asList(newCondition("data", "img", "1234567890"), newCondition("data", "count", "2")), Arrays.asList(newColUpdate("data", "count", "3"), newColUpdate("data", "img", "0987654321")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.REJECTED, results.get(s2bb("00347"))); assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "1" }, { "00347", "data", "img", "1234567890" } }, tableName); // one condition should fail updates.clear(); updates.put(s2bb("00347"), new ConditionalUpdates( Arrays.asList(newCondition("data", "img", "565"), newCondition("data", "count", "1")), Arrays.asList(newColUpdate("data", "count", "3"), newColUpdate("data", "img", "0987654321")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.REJECTED, results.get(s2bb("00347"))); assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "1" }, { "00347", "data", "img", "1234567890" } }, tableName); // both conditions should succeed ConditionalStatus result = client.updateRowConditionally(creds, tableName, s2bb("00347"), new ConditionalUpdates( Arrays.asList(newCondition("data", "img", "1234567890"), newCondition("data", "count", "1")), Arrays.asList(newColUpdate("data", "count", "3"), newColUpdate("data", "img", "0987654321")))); assertEquals(ConditionalStatus.ACCEPTED, result); assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "3" }, { "00347", "data", "img", "0987654321" } }, tableName); client.closeConditionalWriter(cwid); try { client.updateRowsConditionally(cwid, updates); fail("conditional writer not closed"); } catch (UnknownWriter uk) { } String principal; ClusterUser cwuser = null; if (isKerberosEnabled()) { cwuser = getKdc().getClientPrincipal(1); principal = cwuser.getPrincipal(); client.createLocalUser(creds, principal, s2bb("unused")); } else { principal = "cwuser"; // run test with colvis client.createLocalUser(creds, principal, s2bb("bestpasswordever")); } client.changeUserAuthorizations(creds, principal, Collections.singleton(s2bb("A"))); client.grantTablePermission(creds, principal, tableName, TablePermission.WRITE); client.grantTablePermission(creds, principal, tableName, TablePermission.READ); TestProxyClient cwuserProxyClient = null; Client origClient = null; Map<String, String> cwProperties; if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(cwuser.getPrincipal(), cwuser.getKeytab().getAbsolutePath()); final UserGroupInformation cwuserUgi = UserGroupInformation.getCurrentUser(); // Re-login in and make a new connection. Can't use the previous one cwuserProxyClient = new TestProxyClient(hostname, proxyPort, factory, proxyPrimary, cwuserUgi); origClient = client; client = cwuserProxyClient.proxy(); cwProperties = Collections.emptyMap(); } else { cwProperties = Collections.singletonMap("password", "bestpasswordever"); } try { ByteBuffer cwCreds = client.login(principal, cwProperties); cwid = client.createConditionalWriter(cwCreds, tableName, new ConditionalWriterOptions().setAuthorizations(Collections.singleton(s2bb("A")))); updates.clear(); updates.put(s2bb("00348"), new ConditionalUpdates( Arrays.asList(new Condition(new Column(s2bb("data"), s2bb("c"), s2bb("A")))), Arrays.asList(newColUpdate("data", "seq", "1"), newColUpdate("data", "c", "1").setColVisibility(s2bb("A"))))); updates.put(s2bb("00349"), new ConditionalUpdates( Arrays.asList(new Condition(new Column(s2bb("data"), s2bb("c"), s2bb("B")))), Arrays.asList(newColUpdate("data", "seq", "1")))); results = client.updateRowsConditionally(cwid, updates); assertEquals(2, results.size()); assertEquals(ConditionalStatus.ACCEPTED, results.get(s2bb("00348"))); assertEquals(ConditionalStatus.INVISIBLE_VISIBILITY, results.get(s2bb("00349"))); if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } // Verify that the original user can't see the updates with visibilities set assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "3" }, { "00347", "data", "img", "0987654321" }, { "00348", "data", "seq", "1" } }, tableName); if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(cwuser.getPrincipal(), cwuser.getKeytab().getAbsolutePath()); client = cwuserProxyClient.proxy(); } updates.clear(); updates.clear(); updates.put(s2bb("00348"), new ConditionalUpdates( Arrays.asList( new Condition(new Column(s2bb("data"), s2bb("c"), s2bb("A"))).setValue(s2bb("0"))), Arrays.asList(newColUpdate("data", "seq", "2"), newColUpdate("data", "c", "2").setColVisibility(s2bb("A"))))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.REJECTED, results.get(s2bb("00348"))); if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } // Same results as the original user assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "3" }, { "00347", "data", "img", "0987654321" }, { "00348", "data", "seq", "1" } }, tableName); if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(cwuser.getPrincipal(), cwuser.getKeytab().getAbsolutePath()); client = cwuserProxyClient.proxy(); } updates.clear(); updates.put(s2bb("00348"), new ConditionalUpdates( Arrays.asList( new Condition(new Column(s2bb("data"), s2bb("c"), s2bb("A"))).setValue(s2bb("1"))), Arrays.asList(newColUpdate("data", "seq", "2"), newColUpdate("data", "c", "2").setColVisibility(s2bb("A"))))); results = client.updateRowsConditionally(cwid, updates); assertEquals(1, results.size()); assertEquals(ConditionalStatus.ACCEPTED, results.get(s2bb("00348"))); if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); client = origClient; } assertScan(new String[][] { { "00345", "data", "img", "1234567890" }, { "00345", "meta", "seq", "3" }, { "00346", "meta", "seq", "1" }, { "00347", "data", "count", "3" }, { "00347", "data", "img", "0987654321" }, { "00348", "data", "seq", "2" } }, tableName); if (isKerberosEnabled()) { UserGroupInformation.loginUserFromKeytab(cwuser.getPrincipal(), cwuser.getKeytab().getAbsolutePath()); client = cwuserProxyClient.proxy(); } client.closeConditionalWriter(cwid); try { client.updateRowsConditionally(cwid, updates); fail("conditional writer not closed"); } catch (UnknownWriter uk) { } } finally { if (isKerberosEnabled()) { // Close the other client if (null != cwuserProxyClient) { cwuserProxyClient.close(); } UserGroupInformation.loginUserFromKeytab(clientPrincipal, clientKeytab.getAbsolutePath()); // Re-login and restore the original client client = origClient; } client.dropLocalUser(creds, principal); } } private void checkKey(String row, String cf, String cq, String val, KeyValue keyValue) { assertEquals(row, ByteBufferUtil.toString(keyValue.key.row)); assertEquals(cf, ByteBufferUtil.toString(keyValue.key.colFamily)); assertEquals(cq, ByteBufferUtil.toString(keyValue.key.colQualifier)); assertEquals("", ByteBufferUtil.toString(keyValue.key.colVisibility)); assertEquals(val, ByteBufferUtil.toString(keyValue.value)); } // scan metadata for file entries for the given table private int countFiles(String table) throws Exception { Map<String, String> tableIdMap = client.tableIdMap(creds); String tableId = tableIdMap.get(table); Key start = new Key(); start.row = s2bb(tableId + ";"); Key end = new Key(); end.row = s2bb(tableId + "<"); end = client.getFollowing(end, PartialKey.ROW); ScanOptions opt = new ScanOptions(); opt.range = new Range(start, true, end, false); opt.columns = Collections.singletonList(new ScanColumn(s2bb("file"))); String scanner = client.createScanner(creds, MetadataTable.NAME, opt); int result = 0; while (true) { ScanResult more = client.nextK(scanner, 100); result += more.getResults().size(); if (!more.more) break; } return result; } private Map<ByteBuffer, List<ColumnUpdate>> mutation(String row, String cf, String cq, String value) { ColumnUpdate upd = new ColumnUpdate(s2bb(cf), s2bb(cq)); upd.setValue(value.getBytes(UTF_8)); return Collections.singletonMap(s2bb(row), Collections.singletonList(upd)); } private ByteBuffer s2bb(String cf) { return ByteBuffer.wrap(cf.getBytes(UTF_8)); } private Map<String, String> s2pp(String cf) { Map<String, String> toRet = new TreeMap<String, String>(); toRet.put("password", cf); return toRet; } static private ByteBuffer t2bb(Text t) { return ByteBuffer.wrap(t.getBytes()); } @Test public void testGetRowRange() throws Exception { Range range = client.getRowRange(s2bb("xyzzy")); org.apache.accumulo.core.data.Range range2 = new org.apache.accumulo.core.data.Range(new Text("xyzzy")); assertEquals(0, range.start.row.compareTo(t2bb(range2.getStartKey().getRow()))); assertEquals(0, range.stop.row.compareTo(t2bb(range2.getEndKey().getRow()))); assertEquals(range.startInclusive, range2.isStartKeyInclusive()); assertEquals(range.stopInclusive, range2.isEndKeyInclusive()); assertEquals(0, range.start.colFamily.compareTo(t2bb(range2.getStartKey().getColumnFamily()))); assertEquals(0, range.start.colQualifier.compareTo(t2bb(range2.getStartKey().getColumnQualifier()))); assertEquals(0, range.stop.colFamily.compareTo(t2bb(range2.getEndKey().getColumnFamily()))); assertEquals(0, range.stop.colQualifier.compareTo(t2bb(range2.getEndKey().getColumnQualifier()))); assertEquals(range.start.timestamp, range.start.timestamp); assertEquals(range.stop.timestamp, range.stop.timestamp); } @Test public void testCompactionStrategy() throws Exception { File jarDir = new File(System.getProperty("user.dir"), "target"); assertTrue(jarDir.mkdirs() || jarDir.isDirectory()); File jarFile = new File(jarDir, "TestCompactionStrat.jar"); FileUtils.copyInputStreamToFile(Class.class.getResourceAsStream("/TestCompactionStrat.jar"), jarFile); client.setProperty(creds, Property.VFS_CONTEXT_CLASSPATH_PROPERTY.getKey() + "context1", jarFile.toString()); client.setTableProperty(creds, tableName, Property.TABLE_CLASSPATH.getKey(), "context1"); client.addSplits(creds, tableName, Collections.singleton(s2bb("efg"))); client.updateAndFlush(creds, tableName, mutation("a", "cf", "cq", "v1")); client.flushTable(creds, tableName, null, null, true); client.updateAndFlush(creds, tableName, mutation("b", "cf", "cq", "v2")); client.flushTable(creds, tableName, null, null, true); client.updateAndFlush(creds, tableName, mutation("y", "cf", "cq", "v1")); client.flushTable(creds, tableName, null, null, true); client.updateAndFlush(creds, tableName, mutation("z", "cf", "cq", "v2")); client.flushTable(creds, tableName, null, null, true); assertEquals(4, countFiles(tableName)); CompactionStrategyConfig csc = new CompactionStrategyConfig(); // The EfgCompactionStrat will only compact tablets with and end row of efg csc.setClassName("org.apache.accumulo.test.EfgCompactionStrat"); client.compactTable(creds, tableName, null, null, null, true, true, csc); assertEquals(3, countFiles(tableName)); } @Test public void namespaceOperations() throws Exception { // default namespace and accumulo namespace assertEquals("System namespace is wrong", client.systemNamespace(), Namespaces.ACCUMULO_NAMESPACE); assertEquals("Default namespace is wrong", client.defaultNamespace(), Namespaces.DEFAULT_NAMESPACE); // namespace existance and namespace listing assertTrue("Namespace created during setup should exist", client.namespaceExists(creds, namespaceName)); assertTrue("Namespace listing should contain namespace created during setup", client.listNamespaces(creds).contains(namespaceName)); // create new namespace String newNamespace = "foobar"; client.createNamespace(creds, newNamespace); assertTrue("Namespace just created should exist", client.namespaceExists(creds, newNamespace)); assertTrue("Namespace listing should contain just created", client.listNamespaces(creds).contains(newNamespace)); // rename the namespace String renamedNamespace = "foobar_renamed"; client.renameNamespace(creds, newNamespace, renamedNamespace); assertTrue("Renamed namespace should exist", client.namespaceExists(creds, renamedNamespace)); assertTrue("Namespace listing should contain renamed namespace", client.listNamespaces(creds).contains(renamedNamespace)); assertFalse("Original namespace should no longer exist", client.namespaceExists(creds, newNamespace)); assertFalse("Namespace listing should no longer contain original namespace", client.listNamespaces(creds).contains(newNamespace)); // delete the namespace client.deleteNamespace(creds, renamedNamespace); assertFalse("Renamed namespace should no longer exist", client.namespaceExists(creds, renamedNamespace)); assertFalse("Namespace listing should no longer contain renamed namespace", client.listNamespaces(creds).contains(renamedNamespace)); // namespace properties Map<String, String> cfg = client.getNamespaceProperties(creds, namespaceName); String defaultProp = cfg.get("table.compaction.major.ratio"); assertNotEquals(defaultProp, "10"); // let's make sure we are setting this value to something different than default... client.setNamespaceProperty(creds, namespaceName, "table.compaction.major.ratio", "10"); for (int i = 0; i < 5; i++) { cfg = client.getNamespaceProperties(creds, namespaceName); if ("10".equals(cfg.get("table.compaction.major.ratio"))) { break; } sleepUninterruptibly(200, TimeUnit.MILLISECONDS); } assertTrue("Namespace should contain table.compaction.major.ratio property", client.getNamespaceProperties(creds, namespaceName).containsKey("table.compaction.major.ratio")); assertEquals("Namespace property table.compaction.major.ratio property should equal 10", client.getNamespaceProperties(creds, namespaceName).get("table.compaction.major.ratio"), "10"); client.removeNamespaceProperty(creds, namespaceName, "table.compaction.major.ratio"); for (int i = 0; i < 5; i++) { cfg = client.getNamespaceProperties(creds, namespaceName); if (!defaultProp.equals(cfg.get("table.compaction.major.ratio"))) { break; } sleepUninterruptibly(200, TimeUnit.MILLISECONDS); } assertEquals("Namespace should have default value for table.compaction.major.ratio", defaultProp, cfg.get("table.compaction.major.ratio")); // namespace ID map assertTrue("Namespace ID map should contain accumulo", client.namespaceIdMap(creds).containsKey("accumulo")); assertTrue("Namespace ID map should contain namespace created during setup", client.namespaceIdMap(creds).containsKey(namespaceName)); // namespace iterators IteratorSetting setting = new IteratorSetting(100, "DebugTheThings", DebugIterator.class.getName(), Collections.<String, String>emptyMap()); client.attachNamespaceIterator(creds, namespaceName, setting, EnumSet.of(IteratorScope.SCAN)); assertEquals("Wrong iterator setting returned", setting, client.getNamespaceIteratorSetting(creds, namespaceName, "DebugTheThings", IteratorScope.SCAN)); assertTrue("Namespace iterator settings should contain iterator just added", client.listNamespaceIterators(creds, namespaceName).containsKey("DebugTheThings")); assertEquals("Namespace iterator listing should contain iterator scope just added", EnumSet.of(IteratorScope.SCAN), client.listNamespaceIterators(creds, namespaceName).get("DebugTheThings")); client.checkNamespaceIteratorConflicts(creds, namespaceName, setting, EnumSet.of(IteratorScope.MAJC)); client.removeNamespaceIterator(creds, namespaceName, "DebugTheThings", EnumSet.of(IteratorScope.SCAN)); assertFalse("Namespace iterator settings should contain iterator just added", client.listNamespaceIterators(creds, namespaceName).containsKey("DebugTheThings")); // namespace constraints int id = client.addNamespaceConstraint(creds, namespaceName, MaxMutationSize.class.getName()); assertTrue("Namespace should contain max mutation size constraint", client.listNamespaceConstraints(creds, namespaceName).containsKey(MaxMutationSize.class.getName())); assertEquals("Namespace max mutation size constraint id is wrong", id, (int) client.listNamespaceConstraints(creds, namespaceName).get(MaxMutationSize.class.getName())); client.removeNamespaceConstraint(creds, namespaceName, id); assertFalse("Namespace should no longer contain max mutation size constraint", client.listNamespaceConstraints(creds, namespaceName).containsKey(MaxMutationSize.class.getName())); // namespace class load assertTrue("Namespace class load should work", client.testNamespaceClassLoad(creds, namespaceName, DebugIterator.class.getName(), SortedKeyValueIterator.class.getName())); assertFalse("Namespace class load should not work", client.testNamespaceClassLoad(creds, namespaceName, "foo.bar", SortedKeyValueIterator.class.getName())); } }