code: public void clientSessionDidEnd (PresentsSession client)
      {
          if (ignoreClient(client)) {
              return;
          }
  
          // we scan through the list instead of relying on ClientInfo.getKey() because we want
          // derived classes to be able to override that for lookups that happen way more frequently
          // than logging off
          Name username = client.getAuthName();
          for (ClientInfo clinfo : _nodeobj.clients) {
              if (clinfo.username.equals(username)) {
                  _nodeobj.startTransaction();
                  try {
                      // we clear our client info in a transaction so that derived classes can remove
                      // other things from the NodeObject and we'll send that out to all of our peers
                      // in a single compound event
                      clearClientInfo(client, clinfo);
                  } finally {
                      _nodeobj.commitTransaction();
                  }
                  return;
              }
          }
          log.warning("Session ended for unregistered client", "who", username);
      }
docs: from interface ClientManager.ClientObserver