org.apache.hadoop.hbase.client.coprocessor.Batch.Callback#org.apache.hadoop.hbase.DoNotRetryIOException源码实例Demo

下面列出了org.apache.hadoop.hbase.client.coprocessor.Batch.Callback#org.apache.hadoop.hbase.DoNotRetryIOException 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: phoenix   文件: SystemCatalogIT.java
/**
 * Make sure that SYSTEM.CATALOG cannot be split if QueryServices.SYSTEM_CATALOG_SPLITTABLE is false
 */
@Test
public void testSystemTableSplit() throws Exception {
    testUtil = getUtility();
    for (int i=0; i<10; i++) {
        createTable("schema"+i+".table_"+i);
    }
    TableName systemCatalog = TableName.valueOf("SYSTEM.CATALOG");
    RegionLocator rl = testUtil.getConnection().getRegionLocator(systemCatalog);
    assertEquals(rl.getAllRegionLocations().size(), 1);
    try {
        // now attempt to split SYSTEM.CATALOG
        testUtil.getAdmin().split(systemCatalog);
        // make sure the split finishes (there's no synchronous splitting before HBase 2.x)
        testUtil.getAdmin().disableTable(systemCatalog);
        testUtil.getAdmin().enableTable(systemCatalog);
    } catch (DoNotRetryIOException e) {
        // table is not splittable
        assert (e.getMessage().contains("NOT splittable"));
    }

    // test again... Must still be exactly one region.
    rl = testUtil.getConnection().getRegionLocator(systemCatalog);
    assertEquals(1, rl.getAllRegionLocations().size());
}
 
源代码2 项目: phoenix-tephra   文件: TransactionProcessor.java
/**
 * Make sure that the transaction is within the max valid transaction lifetime.
 * @param env {@link RegionCoprocessorEnvironment} of the Region to which the coprocessor is
 *          associated
 * @param op {@link OperationWithAttributes} HBase operation to access its attributes if required
 * @param tx {@link Transaction} supplied by the
 * @throws DoNotRetryIOException thrown if the transaction is older than the max lifetime of a
 *           transaction IOException throw if the value of max lifetime of transaction is
 *           unavailable
 */
protected void ensureValidTxLifetime(RegionCoprocessorEnvironment env,
    @SuppressWarnings("unused") OperationWithAttributes op, @Nullable Transaction tx)
    throws IOException {
  if (tx == null) {
    return;
  }

  boolean validLifetime =
      (TxUtils.getTimestamp(tx.getTransactionId()) + txMaxLifetimeMillis) > System
          .currentTimeMillis();
  if (!validLifetime) {
    throw new DoNotRetryIOException(
        String.format("Transaction %s has exceeded max lifetime %s ms", tx.getTransactionId(),
          txMaxLifetimeMillis));
  }
}
 
源代码3 项目: hbase   文件: TestFIFOCompactionPolicy.java
@Test
public void testSanityCheckBlockingStoreFiles() throws IOException {
  error.expect(DoNotRetryIOException.class);
  error.expectMessage("Blocking file count 'hbase.hstore.blockingStoreFiles'");
  error.expectMessage("is below recommended minimum of 1000 for column family");
  TableName tableName = TableName.valueOf(getClass().getSimpleName() + "-BlockingStoreFiles");
  TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName)
      .setValue(DefaultStoreEngine.DEFAULT_COMPACTION_POLICY_CLASS_KEY,
        FIFOCompactionPolicy.class.getName())
      .setValue(HConstants.HBASE_REGION_SPLIT_POLICY_KEY,
        DisabledRegionSplitPolicy.class.getName())
      .setValue(HStore.BLOCKING_STOREFILES_KEY, "10")
      .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(family).setTimeToLive(1).build())
      .build();
  TEST_UTIL.getAdmin().createTable(desc);
}
 
源代码4 项目: phoenix   文件: BaseScannerRegionObserver.java
private static void throwIfScanOutOfRegion(Scan scan, HRegion region) throws DoNotRetryIOException {
    boolean isLocalIndex = ScanUtil.isLocalIndex(scan);
    byte[] lowerInclusiveScanKey = scan.getStartRow();
    byte[] upperExclusiveScanKey = scan.getStopRow();
    byte[] lowerInclusiveRegionKey = region.getStartKey();
    byte[] upperExclusiveRegionKey = region.getEndKey();
    boolean isStaleRegionBoundaries;
    if (isLocalIndex) {
        byte[] expectedUpperRegionKey = scan.getAttribute(EXPECTED_UPPER_REGION_KEY);
        isStaleRegionBoundaries = expectedUpperRegionKey != null &&
                Bytes.compareTo(upperExclusiveRegionKey, expectedUpperRegionKey) != 0;
    } else {
        isStaleRegionBoundaries = Bytes.compareTo(lowerInclusiveScanKey, lowerInclusiveRegionKey) < 0 ||
                ( Bytes.compareTo(upperExclusiveScanKey, upperExclusiveRegionKey) > 0 && upperExclusiveRegionKey.length != 0);
    }
    if (isStaleRegionBoundaries) {
        Exception cause = new StaleRegionBoundaryCacheException(region.getRegionInfo().getTable().getNameAsString());
        throw new DoNotRetryIOException(cause.getMessage(), cause);
    }
}
 
public static Map<String, Integer> classifyExs(List<Throwable> ths) {
  Map<String, Integer> cls = new HashMap<>();
  for (Throwable t : ths) {
    if (t == null) continue;
    String name = "";
    if (t instanceof DoNotRetryIOException ||
        t instanceof RegionTooBusyException) {
      // If RegionTooBusyException, print message since it has Region name in it.
      // RegionTooBusyException message was edited to remove variance. Has regionname, server,
      // and why the exception; no longer has duration it waited on lock nor current memsize.
      name = t.getMessage();
    } else {
      name = t.getClass().getSimpleName();
    }
    Integer i = cls.get(name);
    if (i == null) {
      i = 0;
    }
    i += 1;
    cls.put(name, i);
  }
  return cls;
}
 
@Test
public void testDeleteWithReadOnly() throws Exception {
  ThriftHBaseServiceHandler handler = createHandler();
  byte[] rowName = Bytes.toBytes("testDelete");
  ByteBuffer table = wrap(tableAname);

  TDelete delete = new TDelete(wrap(rowName));

  boolean exceptionCaught = false;
  try {
    handler.deleteSingle(table, delete);
  } catch (TIOError e) {
    exceptionCaught = true;
    assertTrue(e.getCause() instanceof DoNotRetryIOException);
    assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
  } finally {
    assertTrue(exceptionCaught);
  }
}
 
源代码7 项目: hbase   文件: ProtobufUtil.java
/**
 * Convert a protocol buffer Filter to a client Filter
 *
 * @param proto the protocol buffer Filter to convert
 * @return the converted Filter
 */
@SuppressWarnings("unchecked")
public static Filter toFilter(FilterProtos.Filter proto) throws IOException {
  String type = proto.getName();
  final byte [] value = proto.getSerializedFilter().toByteArray();
  String funcName = "parseFrom";
  try {
    Class<?> c = Class.forName(type, true, ClassLoaderHolder.CLASS_LOADER);
    Method parseFrom = c.getMethod(funcName, byte[].class);
    if (parseFrom == null) {
      throw new IOException("Unable to locate function: " + funcName + " in type: " + type);
    }
    return (Filter)parseFrom.invoke(c, value);
  } catch (Exception e) {
    // Either we couldn't instantiate the method object, or "parseFrom" failed.
    // In either case, let's not retry.
    throw new DoNotRetryIOException(e);
  }
}
 
@Test
public void testIncrementWithReadOnly() throws Exception {
  ThriftHBaseServiceHandler handler = createHandler();
  byte[] rowName = Bytes.toBytes("testIncrement");
  ByteBuffer table = wrap(tableAname);

  List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
  incrementColumns.add(new TColumnIncrement(wrap(familyAname), wrap(qualifierAname)));
  TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);

  boolean exceptionCaught = false;
  try {
    handler.increment(table, increment);
  } catch (TIOError e) {
    exceptionCaught = true;
    assertTrue(e.getCause() instanceof DoNotRetryIOException);
    assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
  } finally {
    assertTrue(exceptionCaught);
  }
}
 
源代码9 项目: phoenix   文件: IndexRebuildRegionScanner.java
private static void applyDeleteOnPut(Delete del, Put put) throws IOException {
    for (List<Cell> cells : del.getFamilyCellMap().values()) {
        for (Cell cell : cells) {
            switch ((KeyValue.Type.codeToType(cell.getTypeByte()))) {
                case DeleteFamily:
                    put.getFamilyCellMap().remove(CellUtil.cloneFamily(cell));
                    break;
                case DeleteColumn:
                    removeColumn(put, cell);
                    break;
                default:
                    // We do not expect this can happen
                    throw new DoNotRetryIOException("Single version delete marker in data mutation " +
                            del);
            }
        }
    }
}
 
源代码10 项目: spliceengine   文件: MemstoreAwareObserverTest.java
@Test
public void preStoreScannerOpenPartitionMiss() throws Exception {
    MemstoreAwareObserver mao = new MemstoreAwareObserver();

    // env and scan do not share same start and end keys (partition miss)
    ObserverContext<RegionCoprocessorEnvironment> fakeCtx = mockRegionEnv(createByteArray(13), createByteArray(24));
    RegionScanner preScanner = mock(RegionScanner.class);

    try {
        mao.postScannerOpen(fakeCtx, mockScan(createByteArray(14), createByteArray(25)), preScanner);
        fail("Expected DoNotRetryIOException");
    } catch (IOException e) {
        // expected
        assertTrue(e instanceof DoNotRetryIOException);
    }
}
 
源代码11 项目: hbase   文件: MasterQuotaManager.java
private void checkQuotaSupport() throws IOException {
  if (!QuotaUtil.isQuotaEnabled(masterServices.getConfiguration())) {
    throw new DoNotRetryIOException(
      new UnsupportedOperationException("quota support disabled"));
  }
  if (!initialized) {
    long maxWaitTime = masterServices.getConfiguration().getLong(
      "hbase.master.wait.for.quota.manager.init", 30000); // default is 30 seconds.
    long startTime = EnvironmentEdgeManager.currentTime();
    do {
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        LOG.warn("Interrupted while waiting for Quota Manager to be initialized.");
        break;
      }
    } while (!initialized && (EnvironmentEdgeManager.currentTime() - startTime) < maxWaitTime);
    if (!initialized) {
      throw new IOException("Quota manager is uninitialized, please retry later.");
    }
  }
}
 
源代码12 项目: hbase   文件: ReplicationPeerManager.java
private void checkQueuesDeleted(String peerId)
    throws ReplicationException, DoNotRetryIOException {
  for (ServerName replicator : queueStorage.getListOfReplicators()) {
    List<String> queueIds = queueStorage.getAllQueues(replicator);
    for (String queueId : queueIds) {
      ReplicationQueueInfo queueInfo = new ReplicationQueueInfo(queueId);
      if (queueInfo.getPeerId().equals(peerId)) {
        throw new DoNotRetryIOException("undeleted queue for peerId: " + peerId +
          ", replicator: " + replicator + ", queueId: " + queueId);
      }
    }
  }
  if (queueStorage.getAllPeersFromHFileRefsQueue().contains(peerId)) {
    throw new DoNotRetryIOException("Undeleted queue for peer " + peerId + " in hfile-refs");
  }
}
 
源代码13 项目: spliceengine   文件: SpliceFailFastInterceptor.java
@Override
public void handleFailure(RetryingCallerInterceptorContext context, Throwable t) throws IOException {

    if (t instanceof UndeclaredThrowableException) {
        t = t.getCause();
    }
    if (t instanceof RemoteException) {
        RemoteException re = (RemoteException)t;
        t = re.unwrapRemoteException();
    }
    if (t instanceof DoNotRetryIOException) {
        throw (DoNotRetryIOException)t;
    }
    if (t instanceof IOException) {
        throw (IOException) t;
    }
    throw new IOException(t);
}
 
源代码14 项目: phoenix   文件: ViewIT.java
private void processTable(String tableName) throws DoNotRetryIOException {
    if (tableName.equals(FAILED_VIEWNAME)) {
        // throwing anything other than instances of IOException result
        // in this coprocessor being unloaded
        // DoNotRetryIOException tells HBase not to retry this mutation
        // multiple times
        throw new DoNotRetryIOException();
    } else if (tableName.startsWith(SLOW_VIEWNAME_PREFIX) || slowDownAddingChildLink) {
        // simulate a slow write to SYSTEM.CATALOG or SYSTEM.CHILD_LINK
        if (latch1 != null) {
            latch1.countDown();
        }
        if (latch2 != null) {
            try {
                // wait till the second task is complete before completing the first task
                boolean result = latch2.await(2, TimeUnit.MINUTES);
                if (!result) {
                    throw new RuntimeException("Second task took took long to complete");
                }
            } catch (InterruptedException e) {
            }
        }
    }
}
 
源代码15 项目: hbase   文件: ServerCall.java
static void setExceptionResponse(Throwable t, String errorMsg,
    ResponseHeader.Builder headerBuilder) {
  ExceptionResponse.Builder exceptionBuilder = ExceptionResponse.newBuilder();
  exceptionBuilder.setExceptionClassName(t.getClass().getName());
  exceptionBuilder.setStackTrace(errorMsg);
  exceptionBuilder.setDoNotRetry(t instanceof DoNotRetryIOException);
  if (t instanceof RegionMovedException) {
    // Special casing for this exception.  This is only one carrying a payload.
    // Do this instead of build a generic system for allowing exceptions carry
    // any kind of payload.
    RegionMovedException rme = (RegionMovedException)t;
    exceptionBuilder.setHostname(rme.getHostname());
    exceptionBuilder.setPort(rme.getPort());
  }
  // Set the exception as the result of the method invocation.
  headerBuilder.setException(exceptionBuilder.build());
}
 
源代码16 项目: hbase   文件: RSRpcServices.java
private void checkShouldRejectReplicationRequest(List<WALEntry> entries) throws IOException {
  ReplicationSourceService replicationSource = regionServer.getReplicationSourceService();
  if (replicationSource == null || entries.isEmpty()) {
    return;
  }
  // We can ensure that all entries are for one peer, so only need to check one entry's
  // table name. if the table hit sync replication at peer side and the peer cluster
  // is (or is transiting to) state ACTIVE or DOWNGRADE_ACTIVE, we should reject to apply
  // those entries according to the design doc.
  TableName table = TableName.valueOf(entries.get(0).getKey().getTableName().toByteArray());
  if (replicationSource.getSyncReplicationPeerInfoProvider().checkState(table,
    RejectReplicationRequestStateChecker.get())) {
    throw new DoNotRetryIOException(
        "Reject to apply to sink cluster because sync replication state of sink cluster "
            + "is ACTIVE or DOWNGRADE_ACTIVE, table: " + table);
  }
}
 
源代码17 项目: hbase   文件: TestScannerWithCorruptHFile.java
@Test(expected = DoNotRetryIOException.class)
public void testScanOnCorruptHFile() throws IOException {
  TableName tableName = TableName.valueOf(name.getMethodName());
  TableDescriptorBuilder.ModifyableTableDescriptor tableDescriptor =
    new TableDescriptorBuilder.ModifyableTableDescriptor(tableName);
  tableDescriptor.setCoprocessor(CorruptHFileCoprocessor.class.getName());
  tableDescriptor.setColumnFamily(
    new ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor(FAMILY_NAME));
  Table table = TEST_UTIL.createTable(tableDescriptor, null);
  try {
    loadTable(table, 1);
    scan(table);
  } finally {
    table.close();
  }
}
 
源代码18 项目: hbase   文件: SplitWALRemoteProcedure.java
@Override
protected void complete(MasterProcedureEnv env, Throwable error) {
  if (error == null) {
    try {
      env.getMasterServices().getSplitWALManager().deleteSplitWAL(walPath);
    } catch (IOException e) {
      LOG.warn("Failed split of {}; ignore...", walPath, e);
    }
    succ = true;
  } else {
    if (error instanceof DoNotRetryIOException) {
      LOG.warn("Sent {} to wrong server {}, try another", walPath, targetServer, error);
      succ = true;
    } else {
      LOG.warn("Failed split of {}, retry...", walPath, error);
      succ = false;
    }
  }
}
 
源代码19 项目: hbase   文件: TestAsyncReplicationAdminApi.java
@Test
public void testInvalidReplicationEndpoint() throws InterruptedException {
  try {
    admin.addReplicationPeer(ID_ONE,
      ReplicationPeerConfig.newBuilder().setReplicationEndpointImpl("whatever").build()).get();
    fail();
  } catch (ExecutionException e) {
    assertThat(e.getCause(), instanceOf(DoNotRetryIOException.class));
    assertThat(e.getCause().getMessage(), startsWith("Can not instantiate"));
  }
}
 
源代码20 项目: phoenix-tephra   文件: TransactionProcessor.java
/**
 * Make sure that the transaction is within the max valid transaction lifetime.
 *
 * @param env {@link RegionCoprocessorEnvironment} of the Region to which the coprocessor is associated
 * @param op {@link OperationWithAttributes} HBase operation to access its attributes if required
 * @param tx {@link Transaction} supplied by the
 * @throws DoNotRetryIOException thrown if the transaction is older than the max lifetime of a transaction
 *         IOException throw if the value of max lifetime of transaction is unavailable
 */
protected void ensureValidTxLifetime(RegionCoprocessorEnvironment env,
                                     @SuppressWarnings("unused") OperationWithAttributes op,
                                     @Nullable Transaction tx) throws IOException {
  if (tx == null) {
    return;
  }

  boolean validLifetime =
    (TxUtils.getTimestamp(tx.getTransactionId()) + txMaxLifetimeMillis) > System.currentTimeMillis();
  if (!validLifetime) {
    throw new DoNotRetryIOException(String.format("Transaction %s has exceeded max lifetime %s ms",
                                                  tx.getTransactionId(), txMaxLifetimeMillis));
  }
}
 
@Override
public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c,
                   final Put put, final WALEdit edit,
                   final Durability durability) throws IOException {
  if (put.getAttribute(TEST_ATTRIBUTE) == null) {
    throw new DoNotRetryIOException("Put should preserve attributes");
  }
  if (put.getDurability() != Durability.USE_DEFAULT) {
    throw new DoNotRetryIOException("Durability is not propagated correctly");
  }
}
 
@Override
public void preDelete(final ObserverContext<RegionCoprocessorEnvironment> c,
                      final Delete delete, final WALEdit edit,
                      final Durability durability) throws IOException {
  if (delete.getAttribute(TEST_ATTRIBUTE) == null) {
    throw new DoNotRetryIOException("Delete should preserve attributes");
  }
  if (delete.getDurability() != Durability.USE_DEFAULT) {
    throw new DoNotRetryIOException("Durability is not propagated correctly");
  }
}
 
源代码23 项目: hbase   文件: RSGroupInfoManagerImpl.java
private void checkOnlineServersOnly(Set<Address> servers) throws IOException {
  // This uglyness is because we only have Address, not ServerName.
  // Online servers are keyed by ServerName.
  Set<Address> onlineServers = new HashSet<>();
  for(ServerName server: masterServices.getServerManager().getOnlineServers().keySet()) {
    onlineServers.add(server.getAddress());
  }
  for (Address address: servers) {
    if (!onlineServers.contains(address)) {
      throw new DoNotRetryIOException("Server " + address +
          " is not an online server in 'default' RSGroup.");
    }
  }
}
 
源代码24 项目: phoenix   文件: IndexRegionObserver.java
private void doPre(ObserverContext<RegionCoprocessorEnvironment> c, BatchMutateContext context,
                   MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException {
    if (ignoreIndexRebuildForTesting && context.rebuild) {
        return;
    }
    long start = EnvironmentEdgeManager.currentTimeMillis();
    try {
        if (failPreIndexUpdatesForTesting) {
            throw new DoNotRetryIOException("Simulating the first (i.e., pre) index table write failure");
        }
        doIndexWritesWithExceptions(context, false);
        metricSource.updatePreIndexUpdateTime(EnvironmentEdgeManager.currentTimeMillis() - start);
        return;
    } catch (Throwable e) {
        metricSource.updatePreIndexUpdateFailureTime(EnvironmentEdgeManager.currentTimeMillis() - start);
        metricSource.incrementPreIndexUpdateFailures();
        // Remove all locks as they are already unlocked. There is no need to unlock them again later when
        // postBatchMutateIndispensably() is called
        removePendingRows(context);
        context.rowLocks.clear();
        if (context.rebuild) {
            throw new IOException(String.format("%s for rebuild", e.getMessage()), e);
        } else {
            rethrowIndexingException(e);
        }
    }
    throw new RuntimeException(
            "Somehow didn't complete the index update, but didn't return succesfully either!");
}
 
@Override
public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c,
                   final Put put, final WALEdit edit,
                   final Durability durability) throws IOException {
  if (put.getAttribute(TEST_ATTRIBUTE) == null) {
    throw new DoNotRetryIOException("Put should preserve attributes");
  }
  if (put.getDurability() != Durability.USE_DEFAULT) {
    throw new DoNotRetryIOException("Durability is not propagated correctly");
  }
}
 
@Override

    public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c, final Put put,
        final WALEdit edit, final Durability durability) throws IOException {
      if (put.getAttribute(TEST_ATTRIBUTE) == null) {
        throw new DoNotRetryIOException("Put should preserve attributes");
      }
      if (put.getDurability() != Durability.USE_DEFAULT) {
        throw new DoNotRetryIOException("Durability is not propagated correctly");
      }
    }
 
@Override
public void preDelete(final ObserverContext<RegionCoprocessorEnvironment> c,
    final Delete delete, final WALEdit edit, final Durability durability) throws IOException {
  if (delete.getAttribute(TEST_ATTRIBUTE) == null) {
    throw new DoNotRetryIOException("Delete should preserve attributes");
  }
  if (delete.getDurability() != Durability.USE_DEFAULT) {
    throw new DoNotRetryIOException("Durability is not propagated correctly");
  }
}
 
@Override
public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c,
                   final Put put, final WALEdit edit,
                   final Durability durability) throws IOException {
  if (put.getAttribute(TEST_ATTRIBUTE) == null) {
    throw new DoNotRetryIOException("Put should preserve attributes");
  }
  if (put.getDurability() != Durability.USE_DEFAULT) {
    throw new DoNotRetryIOException("Durability is not propagated correctly");
  }
}
 
源代码29 项目: phoenix-tephra   文件: TransactionProcessor.java
/**
 * Make sure that the transaction is within the max valid transaction lifetime.
 *
 * @param env {@link RegionCoprocessorEnvironment} of the Region to which the coprocessor is associated
 * @param op {@link OperationWithAttributes} HBase operation to access its attributes if required
 * @param tx {@link Transaction} supplied by the
 * @throws DoNotRetryIOException thrown if the transaction is older than the max lifetime of a transaction
 *         IOException throw if the value of max lifetime of transaction is unavailable
 */
protected void ensureValidTxLifetime(RegionCoprocessorEnvironment env,
                                     @SuppressWarnings("unused") OperationWithAttributes op,
                                     @Nullable Transaction tx) throws IOException {
  if (tx == null) {
    return;
  }

  boolean validLifetime =
    (TxUtils.getTimestamp(tx.getTransactionId()) + txMaxLifetimeMillis) > System.currentTimeMillis();
  if (!validLifetime) {
    throw new DoNotRetryIOException(String.format("Transaction %s has exceeded max lifetime %s ms",
                                                  tx.getTransactionId(), txMaxLifetimeMillis));
  }
}
 
@Override
public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c,
                   final Put put, final WALEdit edit,
                   final Durability durability) throws IOException {
  if (put.getAttribute(TEST_ATTRIBUTE) == null) {
    throw new DoNotRetryIOException("Put should preserve attributes");
  }
  if (put.getDurability() != Durability.USE_DEFAULT) {
    throw new DoNotRetryIOException("Durability is not propagated correctly");
  }
}