package com.jivesoftware.os.amza.service.partition; import com.jivesoftware.os.amza.api.partition.PartitionTx; import com.jivesoftware.os.amza.api.partition.VersionedAquarium; import com.jivesoftware.os.amza.api.partition.VersionedPartitionName; import java.util.concurrent.Semaphore; /** * @author jonathan.colt */ public class VersionedPartitionTransactor { private final Semaphore[] semaphores; private final int numPermits; public VersionedPartitionTransactor(int numSemaphores, int numPermits) { this.semaphores = new Semaphore[numSemaphores]; for (int i = 0; i < numSemaphores; i++) { this.semaphores[i] = new Semaphore(numPermits, true); } this.numPermits = numPermits; } public <R> R doWithOne(VersionedAquarium versionedAquarium, PartitionTx<R> tx) throws Exception { return doWith(versionedAquarium, 1, tx); } public <R> R doWithAll(VersionedAquarium versionedAquarium, PartitionTx<R> tx) throws Exception { return doWith(versionedAquarium, numPermits, tx); } private <R> R doWith(VersionedAquarium versionedAquarium, int count, PartitionTx<R> tx) throws Exception { VersionedPartitionName versionedPartitionName = versionedAquarium.getVersionedPartitionName(); Semaphore semaphore = semaphore(versionedPartitionName); semaphore.acquire(count); try { return tx.tx(versionedAquarium); } finally { semaphore.release(count); } } private Semaphore semaphore(VersionedPartitionName versionedPartitionName) { return semaphores[Math.abs(versionedPartitionName.hashCode() % semaphores.length)]; } }