public void removeFrom(ObjectContainer container, ClientContext context) {
   if (logMINOR) Logger.minor(this, "removeFrom() on " + this);
   container.activate(uri, 5);
   uri.removeFrom(container);
   if (resultingURI != null) {
     container.activate(resultingURI, 5);
     resultingURI.removeFrom(container);
   }
   // cb, parent are responsible for removing themselves
   // ctx is passed in and unmodified - usually the ClientPutter removes it
   container.activate(errors, 5);
   errors.removeFrom(container);
   if (freeData && sourceData != null && container.ext().isStored(sourceData)) {
     Logger.error(this, "Data not removed!");
     container.activate(sourceData, 1);
     sourceData.removeFrom(container);
   }
   container.delete(this);
 }
  @Override
  public void onFailure(
      LowLevelPutException e, Object keyNum, ObjectContainer container, ClientContext context) {
    synchronized (this) {
      if (finished) return;
    }
    if (persistent) container.activate(errors, 1);
    if (parent.isCancelled()) {
      fail(new InsertException(InsertException.CANCELLED), container, context);
      return;
    }
    if (logMINOR) Logger.minor(this, "onFailure() on " + e + " for " + this);

    switch (e.code) {
      case LowLevelPutException.COLLISION:
        fail(new InsertException(InsertException.COLLISION), container, context);
        return;
      case LowLevelPutException.INTERNAL_ERROR:
        fail(new InsertException(InsertException.INTERNAL_ERROR), container, context);
        return;
      case LowLevelPutException.REJECTED_OVERLOAD:
        errors.inc(InsertException.REJECTED_OVERLOAD);
        break;
      case LowLevelPutException.ROUTE_NOT_FOUND:
        errors.inc(InsertException.ROUTE_NOT_FOUND);
        break;
      case LowLevelPutException.ROUTE_REALLY_NOT_FOUND:
        errors.inc(InsertException.ROUTE_REALLY_NOT_FOUND);
        break;
      default:
        Logger.error(this, "Unknown LowLevelPutException code: " + e.code);
        errors.inc(InsertException.INTERNAL_ERROR);
    }
    if (persistent) container.activate(ctx, 1);
    if (e.code == LowLevelPutException.ROUTE_NOT_FOUND
        || e.code == LowLevelPutException.ROUTE_REALLY_NOT_FOUND) {
      consecutiveRNFs++;
      if (logMINOR)
        Logger.minor(
            this,
            "Consecutive RNFs: " + consecutiveRNFs + " / " + ctx.consecutiveRNFsCountAsSuccess);
      if (consecutiveRNFs == ctx.consecutiveRNFsCountAsSuccess) {
        if (logMINOR)
          Logger.minor(this, "Consecutive RNFs: " + consecutiveRNFs + " - counting as success");
        onSuccess(keyNum, container, context);
        return;
      }
    } else consecutiveRNFs = 0;
    if (logMINOR) Logger.minor(this, "Failed: " + e);
    retries++;
    if ((retries > ctx.maxInsertRetries) && (ctx.maxInsertRetries != -1)) {
      fail(InsertException.construct(persistent ? errors.clone() : errors), container, context);
      if (persistent) container.deactivate(ctx, 1);
      return;
    }
    if (persistent) {
      container.store(this);
      container.deactivate(ctx, 1);
    }
    getScheduler(context).registerInsert(this, persistent, false, container);
  }