/**
   * Add additional state-update to record information about a door.
   *
   * @param update the StateUpdate we are to add metrics to.
   * @param pathToDoor a StatePath under which we are to add data.
   * @param info the information about the door.
   * @param lifetime the duration, in seconds, for this information
   */
  private void addDoorInfo(
      StateUpdate update, StatePath pathToDoor, LoginBrokerInfo info, long lifetime) {
    StatePath pathToProtocol = pathToDoor.newChild("protocol");

    conditionalAddString(update, pathToProtocol, "engine", info.getProtocolEngine(), lifetime);
    conditionalAddString(update, pathToProtocol, "family", info.getProtocolFamily(), lifetime);
    conditionalAddString(update, pathToProtocol, "version", info.getProtocolVersion(), lifetime);
    conditionalAddString(update, pathToProtocol, "root", info.getRoot(), lifetime);

    update.appendUpdate(
        pathToDoor.newChild("load"), new FloatingPointStateValue(info.getLoad(), lifetime));
    update.appendUpdate(
        pathToDoor.newChild("port"), new IntegerStateValue(info.getPort(), lifetime));
    update.appendUpdate(
        pathToDoor.newChild("cell"), new StringStateValue(info.getCellName(), lifetime));
    update.appendUpdate(
        pathToDoor.newChild("domain"), new StringStateValue(info.getDomainName(), lifetime));
    update.appendUpdate(
        pathToDoor.newChild("update-time"), new IntegerStateValue(info.getUpdateTime(), lifetime));

    info.getAddresses()
        .stream()
        .forEach(i -> addInterfaceInfo(update, pathToDoor.newChild("interfaces"), i, lifetime));

    update.appendUpdateCollection(pathToDoor.newChild("tags"), info.getTags(), lifetime);
  }
  /**
   * Build a StatePath for a given VO to the summary of that VO's SRM reservations; for example,
   * <code>summary.reservations.by-vo.atlas</code>
   *
   * @param voName The name of the VO
   * @return a StatePath pointing to the "by-description" part of this VO's reservation summary.
   */
  private static StatePath buildVoPath(String voName) {
    if (voName == null) {
      throw new IllegalArgumentException("voName is null");
    }

    return RESERVATIONS_BASE_PATH.newChild(voName);
  }
 /**
  * Purge all IDs that are not present in this ReservationSummaryInfo but are missing from a new
  * version of ReservationSummaryInfo
  *
  * @param update the StateUpdate to add adjust.
  * @param basePath the base path of the IDs
  * @param newInfo the new version of this ReservationSummaryInfo
  */
 public void purgeMissingIds(
     StateUpdate update, StatePath basePath, ReservationSummaryInfo newInfo) {
   for (String id : _ids) {
     if (!newInfo.hasId(id)) {
       update.purgeUnder(basePath.newChild(id));
     }
   }
 }
    /**
     * Update the provided StateUpdate object so that later processing this StateUpdate will alter
     * dCache state such that it reflects the information held in this object.
     *
     * @param update the StateUpdate to use
     * @param voName the name of the VO
     * @param basePath the StatePath under which metrics will be added
     * @param oldInfo the previous ReservationSummaryInfo or null if this description is new.
     */
    public void updateMetrics(
        StateUpdate update, String voName, StatePath basePath, ReservationSummaryInfo oldInfo) {

      StatePath spacePath = basePath.newChild(PATH_ELEMENT_SPACE_BRANCH);

      if (totalNeedsUpdating(oldInfo)) {
        update.appendUpdate(
            spacePath.newChild(PATH_ELEMENT_TOTAL_METRIC), new IntegerStateValue(getTotal(), true));
      }

      if (freeNeedsUpdating(oldInfo)) {
        update.appendUpdate(
            spacePath.newChild(PATH_ELEMENT_FREE_METRIC), new IntegerStateValue(getFree(), true));
      }

      if (allocatedNeedsUpdating(oldInfo)) {
        update.appendUpdate(
            spacePath.newChild(PATH_ELEMENT_ALLOCATED_METRIC),
            new IntegerStateValue(getAllocated(), true));
      }

      if (usedNeedsUpdating(oldInfo)) {
        update.appendUpdate(
            spacePath.newChild(PATH_ELEMENT_USED_METRIC), new IntegerStateValue(getUsed(), true));
      }

      StatePath resvPath = basePath.newChild(PATH_ELEMENT_RESERVATIONS_BRANCH);

      /* Activity if there was an existing summary information */
      if (oldInfo != null) {
        oldInfo.purgeMissingIds(update, resvPath, this);

        /* Add those entries that are new */
        for (String newId : _ids) {
          if (!oldInfo.hasId(newId)) {
            update.appendUpdate(resvPath.newChild(newId), new StateComposite(true));
          }
        }

      } else {
        /* Add the VO name (we need to this only once) */
        update.appendUpdate(
            basePath.newChild(PATH_ELEMENT_VO_NAME_METRIC), new StringStateValue(voName, true));

        /* Add all IDs */
        for (String id : _ids) {
          update.appendUpdate(resvPath.newChild(id), new StateComposite(true));
        }
      }
    }
 public void messageArrived(LoginBrokerInfo info) {
   StateUpdate update = new StateUpdate();
   addDoorInfo(
       update,
       PATH_TO_DOORS.newChild(info.getIdentifier()),
       info,
       TimeUnit.MILLISECONDS.toSeconds((long) (EXPIRATION_FACTOR * info.getUpdateTime())));
   _sum.enqueueUpdate(update);
 }
  /**
   * Add a standardised amount of information about an interface. This is in the form:
   *
   * <pre>
   *     [interfaces]
   *       |
   *       |
   *       +--[ id ] (branch)
   *       |   |
   *       |   +-- "order"  (integer metric: 1 .. 2 ..)
   *       |   +-- "FQDN" (string metric: the host's FQDN, as presented by the door)
   *       |   +-- "address" (string metric: the host's address; e.g., "127.0.0.1")
   *       |   +-- "address-type"    (string metric: "IPv4", "IPv6" or "unknown")
   *       |   +-- "scope"    (string metric: "IPv4", "IPv6" or "unknown")
   *       |
   * </pre>
   *
   * @param update The StateUpdate to append the new metrics.
   * @param parentPath the path that the id branch will be added.
   * @param lifetime how long the created metrics should last.
   */
  private void addInterfaceInfo(
      StateUpdate update, StatePath parentPath, InetAddress address, long lifetime) {
    StatePath pathToInterfaceBranch = parentPath.newChild(address.getHostAddress());

    String hostName = address.getHostName();
    update.appendUpdate(
        pathToInterfaceBranch.newChild("FQDN"), new StringStateValue(hostName, lifetime));

    String urlName = (isInetAddress(hostName)) ? toUriString(address) : hostName;
    update.appendUpdate(
        pathToInterfaceBranch.newChild("url-name"), new StringStateValue(urlName, lifetime));

    update.appendUpdate(
        pathToInterfaceBranch.newChild("address"),
        new StringStateValue(address.getHostAddress(), lifetime));
    update.appendUpdate(
        pathToInterfaceBranch.newChild("address-type"),
        new StringStateValue(
            (address instanceof Inet4Address)
                ? "IPv4"
                : (address instanceof Inet6Address) ? "IPv6" : "unknown",
            lifetime));
    update.appendUpdate(
        pathToInterfaceBranch.newChild("scope"),
        new StringStateValue(NetworkUtils.InetAddressScope.of(address).toString().toLowerCase()));
  }
 /**
  * Add a string metric at a specific point in the State tree if the value is not NULL.
  *
  * @param update the StateUpdate to append with the metric definition
  * @param parentPath the path to the parent branch for this metric
  * @param name the name of the metric
  * @param value the metric's value, or null if the metric should not be added.
  * @param storeTime how long, in seconds the metric should be preserved.
  */
 private void conditionalAddString(
     StateUpdate update, StatePath parentPath, String name, String value, long storeTime) {
   if (value != null) {
     update.appendUpdate(parentPath.newChild(name), new StringStateValue(value, storeTime));
   }
 }
 /**
  * Build a path to a description's summary information based on a voBasePath (something like
  * <code>summary.reservations.by-vo.atlas</code>. The returned path is something like: <code>
  * summary.reservations.by-vo.atlas.by-description.MCDISK</code>
  *
  * @param voBasePath
  * @param description
  * @return
  */
 private static StatePath buildDescriptionPath(StatePath voBasePath, String description) {
   return voBasePath.newChild(PATH_ELEMENT_BY_DESCRIPTION_BRANCH).newChild(description);
 }