/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.kernel.nio.intraband.mailbox;
import com.liferay.portal.kernel.nio.intraband.Datagram;
import com.liferay.portal.kernel.nio.intraband.Intraband;
import com.liferay.portal.kernel.nio.intraband.RegistrationReference;
import com.liferay.portal.kernel.nio.intraband.SystemDataType;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.PropsUtil;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author Shuyang Zhou
*/
public class MailboxUtil {
public static ByteBuffer receiveMail(long receipt) {
ByteBuffer byteBuffer = _mailMap.remove(receipt);
_overdueMailQueue.remove(new ReceiptStub(receipt));
if (!_INTRABAND_MAILBOX_REAPER_THREAD_ENABLED) {
_pollingCleanup();
}
return byteBuffer;
}
public static long sendMail(
RegistrationReference registrationReference, ByteBuffer byteBuffer)
throws MailboxException {
Intraband intraband = registrationReference.getIntraband();
try {
SystemDataType systemDataType = SystemDataType.MAILBOX;
Datagram responseDatagram = intraband.sendSyncDatagram(
registrationReference,
Datagram.createRequestDatagram(
systemDataType.getValue(), byteBuffer));
byteBuffer = responseDatagram.getDataByteBuffer();
return byteBuffer.getLong();
}
catch (Exception e) {
throw new MailboxException(e);
}
}
protected static long depositMail(ByteBuffer byteBuffer) {
long receipt = _receiptGenerator.getAndIncrement();
_mailMap.put(receipt, byteBuffer);
_overdueMailQueue.offer(new ReceiptStub(receipt, System.nanoTime()));
if (!_INTRABAND_MAILBOX_REAPER_THREAD_ENABLED) {
_pollingCleanup();
}
return receipt;
}
private static void _pollingCleanup() {
ReceiptStub receiptStub = null;
while ((receiptStub = _overdueMailQueue.poll()) != null) {
_mailMap.remove(receiptStub.getReceipt());
}
}
private static final boolean _INTRABAND_MAILBOX_REAPER_THREAD_ENABLED =
GetterUtil.getBoolean(
PropsUtil.get(PropsKeys.INTRABAND_MAILBOX_REAPER_THREAD_ENABLED));
private static final long _INTRABAND_MAILBOX_STORAGE_LIFE =
GetterUtil.getLong(
PropsUtil.get(PropsKeys.INTRABAND_MAILBOX_STORAGE_LIFE));
private static final Map<Long, ByteBuffer> _mailMap =
new ConcurrentHashMap<>();
private static final BlockingQueue<ReceiptStub> _overdueMailQueue =
new DelayQueue<>();
private static final AtomicLong _receiptGenerator = new AtomicLong();
private static class OverdueMailReaperThread extends Thread {
@Override
public void run() {
while (true) {
try {
ReceiptStub receiptStub = _overdueMailQueue.take();
_mailMap.remove(receiptStub.getReceipt());
}
catch (InterruptedException ie) {
}
}
}
private OverdueMailReaperThread(String name) {
super(name);
}
}
private static class ReceiptStub implements Delayed {
@Override
public int compareTo(Delayed delayed) {
ReceiptStub receiptStub = (ReceiptStub)delayed;
return (int)(_expireTime - receiptStub._expireTime);
}
@Override
public boolean equals(Object obj) {
ReceiptStub receiptStub = (ReceiptStub)obj;
if (_receipt == receiptStub._receipt) {
return true;
}
return false;
}
@Override
public long getDelay(TimeUnit unit) {
return _expireTime - System.nanoTime();
}
public long getReceipt() {
return _receipt;
}
@Override
public int hashCode() {
return (int)_receipt;
}
private ReceiptStub(long receipt) {
this(receipt, -1);
}
private ReceiptStub(long receipt, long currentNanoTime) {
long expireTime = currentNanoTime;
expireTime += TimeUnit.MILLISECONDS.toNanos(
_INTRABAND_MAILBOX_STORAGE_LIFE);
_expireTime = expireTime;
_receipt = receipt;
}
private final long _expireTime;
private final long _receipt;
}
static {
if (_INTRABAND_MAILBOX_REAPER_THREAD_ENABLED) {
Thread thread = new OverdueMailReaperThread(
MailboxUtil.class.getName());
thread.setContextClassLoader(MailboxUtil.class.getClassLoader());
thread.setDaemon(true);
thread.start();
}
}
}