/*
* Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hazelcast.impl;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.InstanceDestroyedException;
import com.hazelcast.core.Prefix;
import com.hazelcast.impl.base.FactoryAwareNamedProxy;
import com.hazelcast.impl.base.RuntimeInterruptedException;
import com.hazelcast.impl.monitor.LocalSemaphoreStatsImpl;
import com.hazelcast.impl.monitor.SemaphoreOperationsCounter;
import com.hazelcast.monitor.LocalSemaphoreStats;
import com.hazelcast.nio.Data;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static com.hazelcast.nio.IOUtil.toData;
public class SemaphoreProxyImpl extends FactoryAwareNamedProxy implements SemaphoreProxy {
private transient SemaphoreProxy base = null;
Data nameAsData = null;
public SemaphoreProxyImpl(String name, FactoryImpl factory) {
setName(name);
setHazelcastInstance(factory);
base = new SemaphoreProxyReal();
}
private void ensure() {
factory.initialChecks();
if (base == null) {
base = (SemaphoreProxy) factory.getOrCreateProxyByName(name);
}
}
public String getLongName() {
return name;
}
public String getName() {
return name.substring(Prefix.SEMAPHORE.length());
}
Data getNameAsData() {
if (nameAsData == null) {
nameAsData = toData(getName());
}
return nameAsData;
}
public Object getId() {
ensure();
return base.getId();
}
@Override
public String toString() {
return "Semaphore [" + getName() + "]";
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
SemaphoreProxyImpl that = (SemaphoreProxyImpl) o;
return !(name != null ? !name.equals(that.name) : that.name != null);
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
public InstanceType getInstanceType() {
ensure();
return base.getInstanceType();
}
public LocalSemaphoreStats getLocalSemaphoreStats() {
ensure();
return base.getLocalSemaphoreStats();
}
public SemaphoreOperationsCounter getOperationsCounter() {
ensure();
return base.getOperationsCounter();
}
public void acquire() throws InstanceDestroyedException, InterruptedException {
ensure();
base.acquire();
}
public void acquire(int permits) throws InstanceDestroyedException, InterruptedException {
check(permits);
ensure();
base.acquire(permits);
}
public Future acquireAsync() {
return doAsyncAcquire(1, false);
}
public Future acquireAsync(int permits) {
check(permits);
return doAsyncAcquire(permits, false);
}
public void acquireAttach() throws InstanceDestroyedException, InterruptedException {
ensure();
base.acquireAttach();
}
public void acquireAttach(int permits) throws InstanceDestroyedException, InterruptedException {
check(permits);
ensure();
base.acquireAttach(permits);
}
public Future acquireAttachAsync() {
return doAsyncAcquire(1, true);
}
public Future acquireAttachAsync(int permits) {
check(permits);
return doAsyncAcquire(permits, true);
}
public void attach() {
ensure();
base.attach();
}
public void attach(int permits) {
check(permits);
ensure();
base.attach(permits);
}
public int attachedPermits() {
ensure();
return base.attachedPermits();
}
public int availablePermits() {
ensure();
return base.availablePermits();
}
public void detach() {
ensure();
base.detach();
}
public void detach(int permits) {
check(permits);
ensure();
base.detach(permits);
}
public void destroy() {
ensure();
base.destroy();
}
public int drainPermits() {
ensure();
return base.drainPermits();
}
public void reducePermits(int permits) {
check(permits);
ensure();
base.reducePermits(permits);
}
public void release() {
ensure();
base.release();
}
public void release(int permits) {
check(permits);
ensure();
base.release(permits);
}
public void releaseDetach() {
ensure();
base.releaseDetach();
}
public void releaseDetach(int permits) {
check(permits);
ensure();
base.releaseDetach(permits);
}
public boolean tryAcquire() {
ensure();
return base.tryAcquire();
}
public boolean tryAcquire(int permits) {
check(permits);
ensure();
return base.tryAcquire(permits);
}
public boolean tryAcquire(long timeout, TimeUnit unit) throws InstanceDestroyedException, InterruptedException {
ensure();
return base.tryAcquire(timeout, unit);
}
public boolean tryAcquire(int permits, long timeout, TimeUnit timeunit) throws InstanceDestroyedException, InterruptedException {
check(permits, timeout, timeunit);
ensure();
return base.tryAcquire(permits, timeout, timeunit);
}
public boolean tryAcquireAttach() {
ensure();
return base.tryAcquireAttach();
}
public boolean tryAcquireAttach(int permits) {
check(permits);
ensure();
return base.tryAcquireAttach(permits);
}
public boolean tryAcquireAttach(long timeout, TimeUnit timeunit) throws InstanceDestroyedException, InterruptedException {
ensure();
return base.tryAcquireAttach(timeout, timeunit);
}
public boolean tryAcquireAttach(int permits, long timeout, TimeUnit timeunit) throws InstanceDestroyedException, InterruptedException {
check(permits, timeout, timeunit);
ensure();
return base.tryAcquireAttach(permits, timeout, timeunit);
}
private void check(int permits) {
if (permits < 0)
throw new IllegalArgumentException("Number of permits can not be negative: " + permits);
}
private void check(int permits, long timeout, TimeUnit timeunit) {
check(permits);
if (timeout < -1)
throw new IllegalArgumentException("Invalid timeout value: " + timeout);
if (timeunit == null) {
throw new NullPointerException("TimeUnit can not be null.");
}
}
private Future doAsyncAcquire(final Integer permits, final Boolean attach) {
final SemaphoreProxyImpl semaphoreProxy = SemaphoreProxyImpl.this;
AsyncCall call = new AsyncCall() {
@Override
protected void call() {
try {
if (attach)
semaphoreProxy.acquireAttach(permits);
else
semaphoreProxy.acquire(permits);
setResult(null);
} catch (InterruptedException e) {
setResult(e);
} catch (InstanceDestroyedException e) {
e.printStackTrace();
}
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
ConcurrentMapManager.MSemaphore msemaphore = factory.node.concurrentMapManager.new MSemaphore();
return msemaphore.cancelAcquire(getNameAsData());
}
};
factory.node.executorManager.executeAsync(call);
return call;
}
private class SemaphoreProxyReal implements SemaphoreProxy {
SemaphoreOperationsCounter operationsCounter = new SemaphoreOperationsCounter();
public Object getId() {
return name;
}
public InstanceType getInstanceType() {
return InstanceType.SEMAPHORE;
}
public String getLongName() {
return name;
}
public String getName() {
return name.substring(Prefix.SEMAPHORE.length());
}
public void destroy() {
newMSemaphore().destroy(getNameAsData());
factory.destroyInstanceClusterWide(name, null);
}
public void acquire() throws InstanceDestroyedException, InterruptedException {
acquire(1);
}
public void acquire(int permits) throws InstanceDestroyedException, InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
try {
doTryAcquire(permits, false, -1);
} catch (RuntimeInterruptedException e) {
throw new InterruptedException();
}
}
public Future acquireAsync() {
throw new UnsupportedOperationException();
}
public Future acquireAsync(int permits) {
throw new UnsupportedOperationException();
}
public void acquireAttach() throws InstanceDestroyedException, InterruptedException {
acquireAttach(1);
}
public void acquireAttach(int permits) throws InstanceDestroyedException, InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
try {
doTryAcquire(permits, true, -1);
} catch (RuntimeInterruptedException e) {
throw new InterruptedException();
}
}
public Future acquireAttachAsync() {
throw new UnsupportedOperationException();
}
public Future acquireAttachAsync(int permits) {
throw new UnsupportedOperationException();
}
public void attach() {
attach(1);
}
public void attach(int permits) {
newMSemaphore().attachDetach(getNameAsData(), permits);
}
public int attachedPermits() {
return newMSemaphore().getAttached(getNameAsData());
}
public int availablePermits() {
return newMSemaphore().getAvailable(getNameAsData());
}
public void detach() {
detach(1);
}
public void detach(int permits) {
newMSemaphore().attachDetach(getNameAsData(), -permits);
}
public int drainPermits() {
return newMSemaphore().drainPermits(getNameAsData());
}
public void release() {
release(1);
}
public void release(int permits) {
newMSemaphore().release(getNameAsData(), permits, false);
}
public void releaseDetach() {
releaseDetach(1);
}
public void releaseDetach(int permits) {
newMSemaphore().release(getNameAsData(), permits, true);
}
public boolean tryAcquire() {
return tryAcquire(1);
}
public boolean tryAcquire(int permits) {
try {
return doTryAcquire(permits, false, -1);
} catch (Throwable e) {
return false;
}
}
public boolean tryAcquire(long timeout, TimeUnit unit) throws InstanceDestroyedException, InterruptedException {
return tryAcquire(1, timeout, unit);
}
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InstanceDestroyedException, InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
try {
return doTryAcquire(permits, false, unit.toMillis(timeout));
} catch (RuntimeInterruptedException e) {
throw new InterruptedException();
}
}
public boolean tryAcquireAttach() {
return tryAcquireAttach(1);
}
public boolean tryAcquireAttach(int permits) {
try {
return doTryAcquire(permits, true, -1);
} catch (Throwable e) {
return false;
}
}
public boolean tryAcquireAttach(long timeout, TimeUnit unit) throws InstanceDestroyedException, InterruptedException {
return tryAcquireAttach(1, timeout, unit);
}
public boolean tryAcquireAttach(int permits, long timeout, TimeUnit unit) throws InstanceDestroyedException, InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
try {
return doTryAcquire(permits, true, unit.toMillis(timeout));
} catch (RuntimeInterruptedException e) {
throw new InterruptedException();
}
}
public void reducePermits(int permits) {
newMSemaphore().reduce(getNameAsData(), permits);
}
public LocalSemaphoreStats getLocalSemaphoreStats() {
LocalSemaphoreStatsImpl localSemaphoreStats = new LocalSemaphoreStatsImpl();
localSemaphoreStats.setOperationStats(operationsCounter.getPublishedStats());
return localSemaphoreStats;
}
public SemaphoreOperationsCounter getOperationsCounter() {
return operationsCounter;
}
private ConcurrentMapManager.MSemaphore newMSemaphore() {
ConcurrentMapManager.MSemaphore msemaphore = factory.node.concurrentMapManager.new MSemaphore();
msemaphore.setOperationsCounter(operationsCounter);
return msemaphore;
}
private boolean doTryAcquire(int permits, boolean attach, long timeout) throws InstanceDestroyedException {
return newMSemaphore().tryAcquire(getNameAsData(), permits, attach, timeout);
}
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
}
}
}