protected static Address lookupOrCreate(
     final Cluster cluster, final ClusterAddressInfo addrInfo) {
   Address addr = null;
   VmInstance vm = null;
   try {
     addr = Addresses.getInstance().lookupDisabled(addrInfo.getAddress());
     LOG.trace("Found address in the inactive set cache: " + addr);
   } catch (final NoSuchElementException e1) {
     try {
       addr = Addresses.getInstance().lookup(addrInfo.getAddress());
       LOG.trace("Found address in the active set cache: " + addr);
     } catch (final NoSuchElementException e) {
     }
   }
   if (addrInfo.hasMapping()) {
     vm =
         Helper.maybeFindVm(
             addr != null ? addr.getInstanceId() : null,
             addrInfo.getAddress(),
             addrInfo.getInstanceIp());
     if ((addr != null) && (vm != null)) {
       Helper.ensureAllocated(addr, vm);
       clearOrphan(addrInfo);
     } else if (addr != null && !addr.isPending() && vm != null && VmStateSet.DONE.apply(vm)) {
       handleOrphan(cluster, addrInfo);
     } else if ((addr != null && addr.isAssigned() && !addr.isPending()) && (vm == null)) {
       handleOrphan(cluster, addrInfo);
     } else if ((addr == null) && (vm != null)) {
       addr =
           new Address(
               Principals.systemFullName(),
               addrInfo.getAddress(),
               vm.getInstanceUuid(),
               vm.getInstanceId(),
               vm.getPrivateAddress());
       clearOrphan(addrInfo);
     } else if ((addr == null) && (vm == null)) {
       addr = new Address(addrInfo.getAddress(), cluster.getPartition());
       handleOrphan(cluster, addrInfo);
     }
   } else {
     if ((addr != null) && addr.isAssigned() && !addr.isPending()) {
       handleOrphan(cluster, addrInfo);
     } else if ((addr != null)
         && !addr.isAssigned()
         && !addr.isPending()
         && addr.isSystemOwned()) {
       try {
         addr.release();
       } catch (final Exception ex) {
         LOG.error(ex);
       }
     } else if ((addr != null) && Address.Transition.system.equals(addr.getTransition())) {
       handleOrphan(cluster, addrInfo);
     } else if (addr == null) {
       addr = new Address(addrInfo.getAddress(), cluster.getPartition());
       Helper.clearVmState(addrInfo);
     }
   }
   return addr;
 }
    private List<ResourceToken> requestResourceToken(
        final Allocation allocInfo, final int tryAmount, final int maxAmount) throws Exception {
      ServiceConfiguration config =
          Topology.lookup(ClusterController.class, allocInfo.getPartition());
      Cluster cluster = Clusters.lookup(config);
      /**
       * TODO:GRZE: this is the call path which needs to trigger gating.
       * It shouldn't be handled directly here, but instead be handled in {@link ResourceState#requestResourceAllocation().
       *
       */
      if (cluster.getGateLock().readLock().tryLock(60, TimeUnit.SECONDS)) {
        try {
          final ResourceState state = cluster.getNodeState();
          /**
           * NOTE: If the defined instance type has an ordering conflict w/ some other type then it
           * isn't safe to service TWO requests which use differing types during the same resource
           * refresh duty cycle. This determines whether or not an asynchronous allocation is safe
           * to do for the request instance type or whether a synchronous resource availability
           * refresh is needed.
           */
          boolean unorderedType = VmTypes.isUnorderedType(allocInfo.getVmType());
          boolean forceResourceRefresh = state.hasUnorderedTokens() || unorderedType;
          /**
           * GRZE: if the vm type is not "nicely" ordered then we force a refresh of the actual
           * cluster state. Note: we already hold the cluster gating lock here so this update will
           * be mutual exclusive wrt both resource allocations and cluster state updates.
           */
          if (forceResourceRefresh) {
            cluster.refreshResources();
          }
          final List<ResourceToken> tokens =
              state.requestResourceAllocation(allocInfo, tryAmount, maxAmount);
          final Iterator<ResourceToken> tokenIterator = tokens.iterator();
          try {
            final Supplier<ResourceToken> allocator =
                new Supplier<ResourceToken>() {
                  @Override
                  public ResourceToken get() {
                    final ResourceToken ret = tokenIterator.next();
                    allocInfo.getAllocationTokens().add(ret);
                    return ret;
                  }
                };

            RestrictedTypes.allocateUnitlessResources(tokens.size(), allocator);
          } finally {
            // release any tokens that were not allocated
            Iterators.all(
                tokenIterator,
                new Predicate<ResourceToken>() {
                  @Override
                  public boolean apply(final ResourceToken resourceToken) {
                    state.releaseToken(resourceToken);
                    return true;
                  }
                });
          }
          return allocInfo.getAllocationTokens();
        } finally {
          cluster.getGateLock().readLock().unlock();
        }
      } else {
        throw new ServiceStateException(
            "Failed to allocate resources in the zone "
                + cluster.getPartition()
                + ", it is currently locked for maintenance.");
      }
    }
  @Override
  public void fireEvent(final ClockTick event) {
    if (Bootstrap.isFinished() && Hosts.isCoordinator()) {

      final List<ResourceAvailabilityEvent> resourceAvailabilityEvents = Lists.newArrayList();
      final Map<ResourceAvailabilityEvent.ResourceType, AvailabilityAccumulator> availabilities =
          Maps.newEnumMap(ResourceAvailabilityEvent.ResourceType.class);
      final Iterable<VmType> vmTypes = Lists.newArrayList(VmTypes.list());
      for (final Cluster cluster : Clusters.getInstance().listValues()) {
        availabilities.put(Core, new AvailabilityAccumulator(VmType.SizeProperties.Cpu));
        availabilities.put(Disk, new AvailabilityAccumulator(VmType.SizeProperties.Disk));
        availabilities.put(Memory, new AvailabilityAccumulator(VmType.SizeProperties.Memory));

        for (final VmType vmType : vmTypes) {
          final ResourceState.VmTypeAvailability va =
              cluster.getNodeState().getAvailability(vmType.getName());

          resourceAvailabilityEvents.add(
              new ResourceAvailabilityEvent(
                  Instance,
                  new ResourceAvailabilityEvent.Availability(
                      va.getMax(),
                      va.getAvailable(),
                      Lists.<ResourceAvailabilityEvent.Tag>newArrayList(
                          new ResourceAvailabilityEvent.Dimension(
                              "availabilityZone", cluster.getPartition()),
                          new ResourceAvailabilityEvent.Dimension("cluster", cluster.getName()),
                          new ResourceAvailabilityEvent.Type("vm-type", vmType.getName())))));

          for (final AvailabilityAccumulator availability : availabilities.values()) {
            availability.total =
                Math.max(
                    availability.total, va.getMax() * availability.valueExtractor.apply(vmType));
            availability.available =
                Math.max(
                    availability.available,
                    va.getAvailable() * availability.valueExtractor.apply(vmType));
          }
        }

        for (final AvailabilityAccumulator availability : availabilities.values()) {
          availability.rollUp(
              Lists.<ResourceAvailabilityEvent.Tag>newArrayList(
                  new ResourceAvailabilityEvent.Dimension(
                      "availabilityZone", cluster.getPartition()),
                  new ResourceAvailabilityEvent.Dimension("cluster", cluster.getName())));
        }
      }

      for (final Map.Entry<ResourceAvailabilityEvent.ResourceType, AvailabilityAccumulator> entry :
          availabilities.entrySet()) {
        resourceAvailabilityEvents.add(
            new ResourceAvailabilityEvent(entry.getKey(), entry.getValue().availabilities));
      }

      for (final ResourceAvailabilityEvent resourceAvailabilityEvent : resourceAvailabilityEvents)
        try {
          ListenerRegistry.getInstance().fireEvent(resourceAvailabilityEvent);
        } catch (Exception ex) {
          logger.error(ex, ex);
        }
    }
  }