/*
* 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.ItemListener;
import com.hazelcast.core.Prefix;
import com.hazelcast.impl.monitor.LocalQueueStatsImpl;
import com.hazelcast.impl.monitor.QueueOperationsCounter;
import com.hazelcast.monitor.LocalQueueStats;
import com.hazelcast.nio.DataSerializable;
import java.io.*;
import java.util.AbstractQueue;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
public class QProxyImpl extends AbstractQueue implements QProxy, HazelcastInstanceAwareInstance, DataSerializable {
private transient QProxy qproxyReal = null;
private transient FactoryImpl factory = null;
private String name = null;
private BlockingQueueManager blockingQueueManager = null;
private ListenerManager listenerManager = null;
public QProxyImpl() {
}
QProxyImpl(String name, FactoryImpl factory) {
this.name = name;
qproxyReal = new QProxyReal();
setHazelcastInstance(factory);
}
public FactoryImpl getFactory() {
return factory;
}
public String getLongName() {
ensure();
return qproxyReal.getLongName();
}
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
this.factory = (FactoryImpl) hazelcastInstance;
this.blockingQueueManager = factory.node.blockingQueueManager;
this.listenerManager = factory.node.listenerManager;
}
private void ensure() {
factory.initialChecks();
if (qproxyReal == null) {
qproxyReal = (QProxy) factory.getOrCreateProxyByName(name);
}
}
public Object getId() {
ensure();
return qproxyReal.getId();
}
@Override
public String toString() {
return "Queue [" + getName() + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
QProxyImpl qProxy = (QProxyImpl) o;
return !(name != null ? !name.equals(qProxy.name) : qProxy.name != null);
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
public void writeData(DataOutput out) throws IOException {
out.writeUTF(name);
}
public void readData(DataInput in) throws IOException {
name = in.readUTF();
}
private void writeObject(ObjectOutputStream out) throws IOException {
writeData(out);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
readData(in);
}
public LocalQueueStats getLocalQueueStats() {
ensure();
return qproxyReal.getLocalQueueStats();
}
public Iterator iterator() {
ensure();
return qproxyReal.iterator();
}
public int size() {
ensure();
return qproxyReal.size();
}
public void addItemListener(ItemListener listener, boolean includeValue) {
ensure();
qproxyReal.addItemListener(listener, includeValue);
}
public void removeItemListener(ItemListener listener) {
ensure();
qproxyReal.removeItemListener(listener);
}
public String getName() {
ensure();
return qproxyReal.getName();
}
public int drainTo(Collection c) {
ensure();
return qproxyReal.drainTo(c);
}
public int drainTo(Collection c, int maxElements) {
ensure();
return qproxyReal.drainTo(c, maxElements);
}
public void destroy() {
ensure();
qproxyReal.destroy();
}
public InstanceType getInstanceType() {
ensure();
return qproxyReal.getInstanceType();
}
public boolean offer(Object o) {
ensure();
return qproxyReal.offer(o);
}
public boolean offer(Object obj, long timeout, TimeUnit unit) throws InterruptedException {
ensure();
return qproxyReal.offer(obj, timeout, unit);
}
public void put(Object obj) throws InterruptedException {
ensure();
qproxyReal.put(obj);
}
public Object poll() {
ensure();
return qproxyReal.poll();
}
public Object poll(long timeout, TimeUnit unit) throws InterruptedException {
ensure();
return qproxyReal.poll(timeout, unit);
}
public Object take() throws InterruptedException {
ensure();
return qproxyReal.take();
}
public int remainingCapacity() {
ensure();
return qproxyReal.remainingCapacity();
}
public Object peek() {
ensure();
return qproxyReal.peek();
}
public QueueOperationsCounter getQueueOperationCounter() {
return qproxyReal.getQueueOperationCounter();
}
private static void check(Object obj) {
Util.checkSerializable(obj);
}
private class QProxyReal extends AbstractQueue implements QProxy {
private final QueueOperationsCounter operationsCounter = new QueueOperationsCounter();
public QProxyReal() {
}
public LocalQueueStats getLocalQueueStats() {
operationsCounter.incrementOtherOperations();
LocalQueueStatsImpl localQueueStats = blockingQueueManager.getOrCreateBQ(name).getQueueStats();
localQueueStats.setOperationStats(operationsCounter.getPublishedStats());
return localQueueStats;
}
public String getLongName() {
return name;
}
public boolean offer(Object obj) {
check(obj);
try {
return offer(obj, 0, TimeUnit.MILLISECONDS);
} catch (InterruptedException ignored) {
return false;
}
}
public boolean offer(Object obj, long timeout, TimeUnit unit) throws InterruptedException {
check(obj);
if (timeout < 0) {
timeout = 0;
}
boolean result = blockingQueueManager.offer(name, obj, unit.toMillis(timeout));
if (!result) {
operationsCounter.incrementRejectedOffers();
}
operationsCounter.incrementOffers();
return result;
}
public void put(Object obj) throws InterruptedException {
check(obj);
blockingQueueManager.offer(name, obj, -1);
operationsCounter.incrementOffers();
}
public Object peek() {
operationsCounter.incrementOtherOperations();
return blockingQueueManager.peek(name);
}
public Object poll() {
try {
Object result = blockingQueueManager.poll(name, 0);
if (result == null) {
operationsCounter.incrementEmptyPolls();
}
operationsCounter.incrementPolls();
return result;
} catch (InterruptedException e) {
return null;
}
}
public Object poll(long timeout, TimeUnit unit) throws InterruptedException {
if (timeout < 0) {
timeout = 0;
}
Object result = blockingQueueManager.poll(name, unit.toMillis(timeout));
if (result == null) {
operationsCounter.incrementEmptyPolls();
}
operationsCounter.incrementPolls();
return result;
}
public Object take() throws InterruptedException {
Object result = blockingQueueManager.poll(name, -1);
if (result == null) {
operationsCounter.incrementEmptyPolls();
}
operationsCounter.incrementPolls();
return result;
}
public int remainingCapacity() {
operationsCounter.incrementOtherOperations();
BlockingQueueManager.BQ q = blockingQueueManager.getOrCreateBQ(name);
int maxSizePerJVM = q.getMaxSizePerJVM();
if (maxSizePerJVM <= 0) {
return Integer.MAX_VALUE;
} else {
int size = size();
int numberOfMembers = factory.node.getClusterImpl().getMembers().size();
int totalCapacity = numberOfMembers * maxSizePerJVM;
return totalCapacity - size;
}
}
@Override
public Iterator iterator() {
operationsCounter.incrementOtherOperations();
return blockingQueueManager.iterate(name);
}
@Override
public int size() {
operationsCounter.incrementOtherOperations();
return blockingQueueManager.size(name);
}
public void addItemListener(ItemListener listener, boolean includeValue) {
blockingQueueManager.addItemListener(name, listener, includeValue);
}
public void removeItemListener(ItemListener listener) {
blockingQueueManager.removeItemListener(name, listener);
}
public String getName() {
return name.substring(Prefix.QUEUE.length());
}
@Override
public boolean remove(Object obj) {
throw new UnsupportedOperationException();
}
public int drainTo(Collection c) {
return drainTo(c, Integer.MAX_VALUE);
}
public int drainTo(Collection c, int maxElements) {
if (c == null) throw new NullPointerException("drainTo null!");
if (maxElements < 0) throw new IllegalArgumentException("Negative maxElements:" + maxElements);
if (maxElements == 0) return 0;
if (c instanceof QProxy) {
QProxy q = (QProxy) c;
if (q.getName().equals(getName())) {
throw new IllegalArgumentException("Cannot drainTo self!");
}
}
operationsCounter.incrementOtherOperations();
int added = 0;
Object value = null;
do {
value = poll();
if (value != null) {
if (!c.add(value)) {
throw new RuntimeException("drainTo is not able to add!");
}
added++;
}
} while (added < maxElements && value != null);
return added;
}
public void destroy() {
operationsCounter.incrementOtherOperations();
factory.destroyInstanceClusterWide(name, null);
factory.destroyInstanceClusterWide(Prefix.MAP + name, null);
}
public InstanceType getInstanceType() {
return InstanceType.QUEUE;
}
public Object getId() {
return name;
}
public QueueOperationsCounter getQueueOperationCounter() {
return operationsCounter;
}
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
}
}
}