public void close() {
    ClientRequest[] requests;
    if (rebootClient != null) rebootClient.onLostConnection(this);
    if (foreverClient != null) foreverClient.onLostConnection(this);
    boolean dupe;
    SubscribeUSK[] uskSubscriptions2;
    synchronized (this) {
      if (isClosed) {
        Logger.error(this, "Already closed: " + this, new Exception("debug"));
        return;
      }
      isClosed = true;
      requests = new ClientRequest[requestsByIdentifier.size()];
      requests = requestsByIdentifier.values().toArray(requests);
      requestsByIdentifier.clear();
      uskSubscriptions2 =
          uskSubscriptions.values().toArray(new SubscribeUSK[uskSubscriptions.size()]);
      dupe = killedDupe;
    }
    for (ClientRequest req : requests) req.onLostConnection(null, server.core.clientContext);
    for (SubscribeUSK sub : uskSubscriptions2) sub.unsubscribe();
    if (!dupe) {
      try {
        server.core.clientContext.jobRunner.queue(
            new DBJob() {

              public boolean run(ObjectContainer container, ClientContext context) {
                if ((rebootClient != null) && !rebootClient.hasPersistentRequests(null))
                  server.unregisterClient(rebootClient, null);
                if (foreverClient != null) {
                  if (!container.ext().isStored(foreverClient)) {
                    Logger.normal(
                        this,
                        "foreverClient is not stored in the database in lost connection non-dupe callback; not deleting it");
                    return false;
                  }
                  container.activate(foreverClient, 1);
                  if (!foreverClient.hasPersistentRequests(container))
                    server.unregisterClient(foreverClient, container);
                  container.deactivate(foreverClient, 1);
                }
                return false;
              }
            },
            NativeThread.NORM_PRIORITY,
            false);
      } catch (DatabaseDisabledException e) {
        // Ignore
      }
    }

    outputHandler.onClosed();
  }
 public void unsubscribeUSK(String identifier) throws MessageInvalidException {
   SubscribeUSK sub;
   synchronized (this) {
     if (!uskSubscriptions.containsKey(identifier))
       throw new MessageInvalidException(
           ProtocolErrorMessage.NO_SUCH_IDENTIFIER,
           "No such identifier unsubscribing",
           identifier,
           false);
     sub = uskSubscriptions.remove(identifier);
   }
   sub.unsubscribe();
 }