You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@accumulo.apache.org by GitBox <gi...@apache.org> on 2018/01/30 21:21:18 UTC

[GitHub] milleruntime closed pull request #364: ACCUMULO-4778 Initial feedback for table name to id mapping cache

milleruntime closed pull request #364: ACCUMULO-4778 Initial feedback for table name to id mapping cache
URL: https://github.com/apache/accumulo/pull/364
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java
index f5e1fa0499..e7a6d73583 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java
@@ -19,37 +19,26 @@
 import static com.google.common.base.Preconditions.checkArgument;
 
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
 import org.apache.accumulo.core.client.BatchWriter;
 import org.apache.accumulo.core.client.BatchWriterConfig;
-import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.MultiTableBatchWriter;
 import org.apache.accumulo.core.client.MutationsRejectedException;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.TableOfflineException;
 import org.apache.accumulo.core.data.Mutation;
-import org.apache.accumulo.core.master.state.tables.TableState;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
 import com.google.common.util.concurrent.UncheckedExecutionException;
 
 public class MultiTableBatchWriterImpl implements MultiTableBatchWriter {
-  public static final long DEFAULT_CACHE_TIME = 200;
-  public static final TimeUnit DEFAULT_CACHE_TIME_UNIT = TimeUnit.MILLISECONDS;
 
   private static final Logger log = LoggerFactory.getLogger(MultiTableBatchWriterImpl.class);
   private AtomicBoolean closed;
-  private AtomicLong cacheLastState;
 
   private class TableBatchWriter implements BatchWriter {
 
@@ -82,49 +71,17 @@ public void flush() {
 
   }
 
-  /**
-   * CacheLoader which will look up the internal table ID for a given table name.
-   */
-  private class TableNameToIdLoader extends CacheLoader<String,String> {
-
-    @Override
-    public String load(String tableName) throws Exception {
-      Instance instance = context.getInstance();
-      String tableId = Tables.getNameToIdMap(instance).get(tableName);
-
-      if (tableId == null)
-        throw new TableNotFoundException(null, tableName, null);
-
-      if (Tables.getTableState(instance, tableId) == TableState.OFFLINE)
-        throw new TableOfflineException(instance, tableId);
-
-      return tableId;
-    }
-
-  }
-
   private TabletServerBatchWriter bw;
   private ConcurrentHashMap<String,BatchWriter> tableWriters;
   private final ClientContext context;
-  private final LoadingCache<String,String> nameToIdCache;
 
   public MultiTableBatchWriterImpl(ClientContext context, BatchWriterConfig config) {
-    this(context, config, DEFAULT_CACHE_TIME, DEFAULT_CACHE_TIME_UNIT);
-  }
-
-  public MultiTableBatchWriterImpl(ClientContext context, BatchWriterConfig config, long cacheTime, TimeUnit cacheTimeUnit) {
     checkArgument(context != null, "context is null");
     checkArgument(config != null, "config is null");
-    checkArgument(cacheTimeUnit != null, "cacheTimeUnit is null");
     this.context = context;
     this.bw = new TabletServerBatchWriter(context, config);
     tableWriters = new ConcurrentHashMap<>();
     this.closed = new AtomicBoolean(false);
-    this.cacheLastState = new AtomicLong(0);
-
-    // Potentially up to ~500k used to cache names to IDs with "segments" of (maybe) ~1000 entries
-    nameToIdCache = CacheBuilder.newBuilder().expireAfterWrite(cacheTime, cacheTimeUnit).concurrencyLevel(10).maximumSize(10000).initialCapacity(20)
-        .build(new TableNameToIdLoader());
   }
 
   @Override
@@ -161,7 +118,7 @@ protected void finalize() {
    */
   private String getId(String tableName) throws TableNotFoundException {
     try {
-      return nameToIdCache.get(tableName);
+      return Tables.getTableId(context.inst, tableName);
     } catch (UncheckedExecutionException e) {
       Throwable cause = e.getCause();
 
@@ -176,20 +133,6 @@ private String getId(String tableName) throws TableNotFoundException {
       }
 
       throw e;
-    } catch (ExecutionException e) {
-      Throwable cause = e.getCause();
-
-      log.error("Unexpected exception when fetching table id for " + tableName);
-
-      if (null == cause) {
-        throw new RuntimeException(e);
-      } else if (cause instanceof TableNotFoundException) {
-        throw (TableNotFoundException) cause;
-      } else if (cause instanceof TableOfflineException) {
-        throw (TableOfflineException) cause;
-      }
-
-      throw new RuntimeException(e);
     }
   }
 
@@ -197,26 +140,6 @@ private String getId(String tableName) throws TableNotFoundException {
   public BatchWriter getBatchWriter(String tableName) throws AccumuloException, AccumuloSecurityException, TableNotFoundException {
     checkArgument(tableName != null, "tableName is null");
 
-    while (true) {
-      long cacheResetCount = Tables.getCacheResetCount();
-
-      // cacheResetCount could change after this point in time, but I think thats ok because just want to ensure this methods sees changes
-      // made before it was called.
-
-      long internalResetCount = cacheLastState.get();
-
-      if (cacheResetCount > internalResetCount) {
-        if (!cacheLastState.compareAndSet(internalResetCount, cacheResetCount)) {
-          continue; // concurrent operation, lets not possibly move cacheLastState backwards in the case where a thread pauses for along time
-        }
-
-        nameToIdCache.invalidateAll();
-        break;
-      }
-
-      break;
-    }
-
     String tableId = getId(tableName);
 
     BatchWriter tbw = tableWriters.get(tableId);
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/TableMap.java b/core/src/main/java/org/apache/accumulo/core/client/impl/TableMap.java
new file mode 100644
index 0000000000..3f3d90c38a
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/TableMap.java
@@ -0,0 +1,100 @@
+/*
+ * 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.core.client.impl;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.accumulo.core.client.impl.Tables.qualified;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.Instance;
+import org.apache.accumulo.core.client.NamespaceNotFoundException;
+import org.apache.accumulo.core.zookeeper.ZooUtil;
+import org.apache.accumulo.fate.zookeeper.ZooCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Used for thread safe caching of immutable table ID maps. See ACCUMULO-4778.
+ */
+public class TableMap {
+  private static final Logger log = LoggerFactory.getLogger(TableMap.class);
+
+  private final Map<String,String> tableNameToIdMap;
+  private final Map<String,String> tableIdToNameMap;
+
+  public TableMap(Instance instance, ZooCache zooCache) {
+    List<String> tableIds = zooCache.getChildren(ZooUtil.getRoot(instance) + Constants.ZTABLES);
+    Map<String,String> namespaceIdToNameMap = new HashMap<>();
+    ImmutableMap.Builder<String,String> tableNameToIdBuilder = new ImmutableMap.Builder<>();
+    ImmutableMap.Builder<String,String> tableIdToNameBuilder = new ImmutableMap.Builder<>();
+    // use StringBuilder to construct zPath string efficiently across many tables
+    StringBuilder zPathBuilder = new StringBuilder();
+    zPathBuilder.append(ZooUtil.getRoot(instance)).append(Constants.ZTABLES).append("/");
+    int prefixLength = zPathBuilder.length();
+
+    for (String tableId : tableIds) {
+      // reset StringBuilder to prefix length before appending ID and suffix
+      zPathBuilder.setLength(prefixLength);
+      zPathBuilder.append(tableId).append(Constants.ZTABLE_NAME);
+      byte[] tableName = zooCache.get(zPathBuilder.toString());
+      zPathBuilder.setLength(prefixLength);
+      zPathBuilder.append(tableId).append(Constants.ZTABLE_NAMESPACE);
+      byte[] nId = zooCache.get(zPathBuilder.toString());
+
+      String namespaceName = Namespaces.DEFAULT_NAMESPACE;
+      // create fully qualified table name
+      if (nId == null) {
+        namespaceName = null;
+      } else {
+        String namespaceId = new String(nId, UTF_8);
+        if (!namespaceId.equals(Namespaces.DEFAULT_NAMESPACE_ID)) {
+          try {
+            namespaceName = namespaceIdToNameMap.get(namespaceId);
+            if (namespaceName == null) {
+              namespaceName = Namespaces.getNamespaceName(instance, namespaceId);
+              namespaceIdToNameMap.put(namespaceId, namespaceName);
+            }
+          } catch (NamespaceNotFoundException e) {
+            log.error("Table (" + tableId + ") contains reference to namespace (" + namespaceId + ") that doesn't exist", e);
+            continue;
+          }
+        }
+      }
+      if (tableName != null && namespaceName != null) {
+        String tableNameStr = qualified(new String(tableName, UTF_8), namespaceName);
+        tableNameToIdBuilder.put(tableNameStr, tableId);
+        tableIdToNameBuilder.put(tableId, tableNameStr);
+      }
+    }
+    tableNameToIdMap = tableNameToIdBuilder.build();
+    tableIdToNameMap = tableIdToNameBuilder.build();
+  }
+
+  public Map<String,String> getNameToIdMap() {
+    return tableNameToIdMap;
+  }
+
+  public Map<String,String> getIdtoNameMap() {
+    return tableIdToNameMap;
+  }
+}
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
index fcf838f692..a93347c216 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
@@ -20,12 +20,11 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.security.SecurityPermission;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.Instance;
@@ -37,64 +36,49 @@
 import org.apache.accumulo.core.zookeeper.ZooUtil;
 import org.apache.accumulo.fate.zookeeper.ZooCache;
 import org.apache.accumulo.fate.zookeeper.ZooCacheFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
 
 public class Tables {
-  private static final Logger log = LoggerFactory.getLogger(Tables.class);
 
   public static final String VALID_NAME_REGEX = "^(\\w+\\.)?(\\w+)$";
 
   private static final SecurityPermission TABLES_PERMISSION = new SecurityPermission("tablesPermission");
-  private static final AtomicLong cacheResetCount = new AtomicLong(0);
+  // Per instance cache will expire after 10 minutes in case we encounter an instance not used frequently
+  private static Cache<String,TableMap> instanceToMapCache = CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).build();
+  private static Cache<String,ZooCache> instanceToZooCache = CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).build();
 
-  private static ZooCache getZooCache(Instance instance) {
+  /**
+   * Return the cached ZooCache for provided instance. ZooCache is initially created with a watcher that will clear the TableMap cache for that instance when
+   * WatchedEvent occurs.
+   */
+  private static ZooCache getZooCache(final Instance instance) {
     SecurityManager sm = System.getSecurityManager();
     if (sm != null) {
       sm.checkPermission(TABLES_PERMISSION);
     }
-    return new ZooCacheFactory().getZooCache(instance.getZooKeepers(), instance.getZooKeepersSessionTimeOut());
-  }
+    final String zks = instance.getZooKeepers();
+    final int timeOut = instance.getZooKeepersSessionTimeOut();
+    final String uuid = instance.getInstanceID();
 
-  private static SortedMap<String,String> getMap(Instance instance, boolean nameAsKey) {
-    ZooCache zc = getZooCache(instance);
-
-    List<String> tableIds = zc.getChildren(ZooUtil.getRoot(instance) + Constants.ZTABLES);
-    TreeMap<String,String> tableMap = new TreeMap<>();
-    Map<String,String> namespaceIdToNameMap = new HashMap<>();
-
-    for (String tableId : tableIds) {
-      byte[] tableName = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAME);
-      byte[] nId = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + tableId + Constants.ZTABLE_NAMESPACE);
-      String namespaceName = Namespaces.DEFAULT_NAMESPACE;
-      // create fully qualified table name
-      if (nId == null) {
-        namespaceName = null;
-      } else {
-        String namespaceId = new String(nId, UTF_8);
-        if (!namespaceId.equals(Namespaces.DEFAULT_NAMESPACE_ID)) {
-          try {
-            namespaceName = namespaceIdToNameMap.get(namespaceId);
-            if (namespaceName == null) {
-              namespaceName = Namespaces.getNamespaceName(instance, namespaceId);
-              namespaceIdToNameMap.put(namespaceId, namespaceName);
+    try {
+      return instanceToZooCache.get(uuid, new Callable<ZooCache>() {
+        @Override
+        public ZooCache call() {
+          return new ZooCacheFactory().getZooCache(zks, timeOut, new Watcher() {
+            @Override
+            public void process(WatchedEvent watchedEvent) {
+              instanceToMapCache.invalidate(uuid);
             }
-          } catch (NamespaceNotFoundException e) {
-            log.error("Table (" + tableId + ") contains reference to namespace (" + namespaceId + ") that doesn't exist", e);
-            continue;
-          }
+          });
         }
-      }
-      if (tableName != null && namespaceName != null) {
-        String tableNameStr = qualified(new String(tableName, UTF_8), namespaceName);
-        if (nameAsKey)
-          tableMap.put(tableNameStr, tableId);
-        else
-          tableMap.put(tableId, tableNameStr);
-      }
+      });
+    } catch (ExecutionException e) {
+      throw new RuntimeException(e);
     }
-
-    return tableMap;
   }
 
   public static String getTableId(Instance instance, String tableName) throws TableNotFoundException {
@@ -129,12 +113,31 @@ public static String getTableName(Instance instance, String tableId) throws Tabl
     return tableName;
   }
 
-  public static SortedMap<String,String> getNameToIdMap(Instance instance) {
-    return getMap(instance, true);
+  public static Map<String,String> getNameToIdMap(Instance instance) {
+    return getTableMap(instance).getNameToIdMap();
+  }
+
+  public static Map<String,String> getIdToNameMap(Instance instance) {
+    return getTableMap(instance).getIdtoNameMap();
   }
 
-  public static SortedMap<String,String> getIdToNameMap(Instance instance) {
-    return getMap(instance, false);
+  /**
+   * Get the TableMap from the cache. A new one will be populated when needed. Cache is cleared manually by calling {@link #clearCache(Instance)} or
+   * automatically cleared by ZooCache watcher created in {@link #getZooCache(Instance)}. See ACCUMULO-4778.
+   */
+  private static TableMap getTableMap(final Instance instance) {
+    TableMap map;
+    try {
+      map = instanceToMapCache.get(instance.getInstanceID(), new Callable<TableMap>() {
+        @Override
+        public TableMap call() {
+          return new TableMap(instance, getZooCache(instance));
+        }
+      });
+    } catch (ExecutionException e) {
+      throw new RuntimeException(e);
+    }
+    return map;
   }
 
   public static boolean exists(Instance instance, String tableId) {
@@ -144,9 +147,9 @@ public static boolean exists(Instance instance, String tableId) {
   }
 
   public static void clearCache(Instance instance) {
-    cacheResetCount.incrementAndGet();
     getZooCache(instance).clear(ZooUtil.getRoot(instance) + Constants.ZTABLES);
     getZooCache(instance).clear(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES);
+    instanceToMapCache.invalidate(instance.getInstanceID());
   }
 
   /**
@@ -158,17 +161,9 @@ public static void clearCache(Instance instance) {
    *          A zookeeper path
    */
   public static void clearCacheByPath(Instance instance, final String zooPath) {
-
-    String thePath;
-
-    if (zooPath.startsWith("/")) {
-      thePath = zooPath;
-    } else {
-      thePath = "/" + zooPath;
-    }
-
+    String thePath = zooPath.startsWith("/") ? zooPath : "/" + zooPath;
     getZooCache(instance).clear(ZooUtil.getRoot(instance) + thePath);
-
+    instanceToMapCache.invalidate(instance.getInstanceID());
   }
 
   public static String getPrintableTableNameFromId(Map<String,String> tidToNameMap, String tableId) {
@@ -229,10 +224,6 @@ public static TableState getTableState(Instance instance, String tableId, boolea
 
   }
 
-  public static long getCacheResetCount() {
-    return cacheResetCount.get();
-  }
-
   public static String qualified(String tableName) {
     return qualified(tableName, Namespaces.DEFAULT_NAMESPACE);
   }
diff --git a/test/src/test/java/org/apache/accumulo/test/MultiTableBatchWriterIT.java b/test/src/test/java/org/apache/accumulo/test/MultiTableBatchWriterIT.java
index f9720f044a..fa5d8bb1d0 100644
--- a/test/src/test/java/org/apache/accumulo/test/MultiTableBatchWriterIT.java
+++ b/test/src/test/java/org/apache/accumulo/test/MultiTableBatchWriterIT.java
@@ -20,7 +20,6 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.concurrent.TimeUnit;
 
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
@@ -31,7 +30,6 @@
 import org.apache.accumulo.core.client.MutationsRejectedException;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.TableNotFoundException;
-import org.apache.accumulo.core.client.TableOfflineException;
 import org.apache.accumulo.core.client.admin.TableOperations;
 import org.apache.accumulo.core.client.impl.ClientContext;
 import org.apache.accumulo.core.client.impl.Credentials;
@@ -61,12 +59,12 @@ public int defaultTimeoutSeconds() {
   @Before
   public void setUpArgs() throws AccumuloException, AccumuloSecurityException {
     connector = getConnector();
-    mtbw = getMultiTableBatchWriter(60);
+    mtbw = getMultiTableBatchWriter();
   }
 
-  public MultiTableBatchWriter getMultiTableBatchWriter(long cacheTimeoutInSeconds) {
+  public MultiTableBatchWriter getMultiTableBatchWriter() {
     ClientContext context = new ClientContext(connector.getInstance(), new Credentials(getAdminPrincipal(), getAdminToken()), getCluster().getClientConfig());
-    return new MultiTableBatchWriterImpl(context, new BatchWriterConfig(), cacheTimeoutInSeconds, TimeUnit.SECONDS);
+    return new MultiTableBatchWriterImpl(context, new BatchWriterConfig());
   }
 
   @Test
@@ -265,7 +263,7 @@ public void testTableRenameNewWriters() throws Exception {
 
   @Test
   public void testTableRenameNewWritersNoCaching() throws Exception {
-    mtbw = getMultiTableBatchWriter(0);
+    mtbw = getMultiTableBatchWriter();
 
     try {
       final String[] names = getUniqueNames(4);
@@ -406,113 +404,4 @@ public void testOfflineTable() throws Exception {
 
     Assert.assertTrue("Expected mutations to be rejected.", mutationsRejected);
   }
-
-  @Test
-  public void testOfflineTableWithCache() throws Exception {
-    boolean mutationsRejected = false;
-
-    try {
-      final String[] names = getUniqueNames(2);
-      final String table1 = names[0], table2 = names[1];
-
-      TableOperations tops = connector.tableOperations();
-      tops.create(table1);
-      tops.create(table2);
-
-      BatchWriter bw1 = mtbw.getBatchWriter(table1), bw2 = mtbw.getBatchWriter(table2);
-
-      Mutation m1 = new Mutation("foo");
-      m1.put("col1", "", "val1");
-      m1.put("col2", "", "val2");
-
-      bw1.addMutation(m1);
-      bw2.addMutation(m1);
-
-      tops.offline(table1);
-
-      try {
-        bw1 = mtbw.getBatchWriter(table1);
-      } catch (TableOfflineException e) {
-        // pass
-        mutationsRejected = true;
-      }
-
-      tops.offline(table2);
-
-      try {
-        bw2 = mtbw.getBatchWriter(table2);
-      } catch (TableOfflineException e) {
-        // pass
-        mutationsRejected = true;
-      }
-    } finally {
-      if (null != mtbw) {
-        try {
-          // Mutations might have flushed before the table offline occurred
-          mtbw.close();
-        } catch (MutationsRejectedException e) {
-          // Pass
-          mutationsRejected = true;
-        }
-      }
-    }
-
-    Assert.assertTrue("Expected mutations to be rejected.", mutationsRejected);
-  }
-
-  @Test
-  public void testOfflineTableWithoutCache() throws Exception {
-    mtbw = getMultiTableBatchWriter(0);
-    boolean mutationsRejected = false;
-
-    try {
-      final String[] names = getUniqueNames(2);
-      final String table1 = names[0], table2 = names[1];
-
-      TableOperations tops = connector.tableOperations();
-      tops.create(table1);
-      tops.create(table2);
-
-      BatchWriter bw1 = mtbw.getBatchWriter(table1), bw2 = mtbw.getBatchWriter(table2);
-
-      Mutation m1 = new Mutation("foo");
-      m1.put("col1", "", "val1");
-      m1.put("col2", "", "val2");
-
-      bw1.addMutation(m1);
-      bw2.addMutation(m1);
-
-      // Mutations might or might not flush before tables goes offline
-      tops.offline(table1);
-      tops.offline(table2);
-
-      try {
-        bw1 = mtbw.getBatchWriter(table1);
-        Assert.fail(table1 + " should be offline");
-      } catch (TableOfflineException e) {
-        // pass
-        mutationsRejected = true;
-      }
-
-      try {
-        bw2 = mtbw.getBatchWriter(table2);
-        Assert.fail(table1 + " should be offline");
-      } catch (TableOfflineException e) {
-        // pass
-        mutationsRejected = true;
-      }
-    } finally {
-      if (null != mtbw) {
-        try {
-          // Mutations might have flushed before the table offline occurred
-          mtbw.close();
-        } catch (MutationsRejectedException e) {
-          // Pass
-          mutationsRejected = true;
-        }
-      }
-    }
-
-    Assert.assertTrue("Expected mutations to be rejected.", mutationsRejected);
-  }
 }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services