@Override
  public boolean release(List<Resource> resources, List<ResourceConsumer> consumers) {
    checkNotNull(resources);
    checkNotNull(consumers);
    checkArgument(resources.size() == consumers.size());

    TransactionContext tx = service.transactionContextBuilder().build();
    tx.begin();

    TransactionalMap<DiscreteResource, ResourceConsumer> discreteConsumerTxMap =
        tx.getTransactionalMap(DISCRETE_CONSUMER_MAP, SERIALIZER);
    TransactionalMap<ResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
        tx.getTransactionalMap(CONTINUOUS_CONSUMER_MAP, SERIALIZER);
    Iterator<Resource> resourceIte = resources.iterator();
    Iterator<ResourceConsumer> consumerIte = consumers.iterator();

    while (resourceIte.hasNext() && consumerIte.hasNext()) {
      Resource resource = resourceIte.next();
      ResourceConsumer consumer = consumerIte.next();

      if (resource instanceof DiscreteResource) {
        // if this single release fails (because the resource is allocated to another consumer,
        // the whole release fails
        if (!discreteConsumerTxMap.remove((DiscreteResource) resource, consumer)) {
          return abortTransaction(tx);
        }
      } else if (resource instanceof ContinuousResource) {
        ContinuousResource continuous = (ContinuousResource) resource;
        ContinuousResourceAllocation allocation = continuousConsumerTxMap.get(continuous.id());
        ImmutableList<ResourceAllocation> newAllocations =
            allocation
                .allocations()
                .stream()
                .filter(
                    x ->
                        !(x.consumer().equals(consumer)
                            && ((ContinuousResource) x.resource()).value() == continuous.value()))
                .collect(GuavaCollectors.toImmutableList());

        if (!continuousConsumerTxMap.replace(
            continuous.id(),
            allocation,
            new ContinuousResourceAllocation(allocation.original(), newAllocations))) {
          return abortTransaction(tx);
        }
      }
    }

    return tx.commit();
  }
  private List<ResourceConsumer> getConsumers(ContinuousResource resource) {
    Versioned<ContinuousResourceAllocation> allocations = continuousConsumers.get(resource.id());
    if (allocations == null) {
      return ImmutableList.of();
    }

    return allocations
        .value()
        .allocations()
        .stream()
        .filter(x -> x.resource().equals(resource))
        .map(ResourceAllocation::consumer)
        .collect(GuavaCollectors.toImmutableList());
  }