package center.system;
import center.task.api.ITaskAPI;
import java.util.HashMap;
import java.util.Map;
import java.util.Date;
import ru.vassaev.core.exception.SysException;
/**
* Информационный фонд точка-точка
* Использование:
* 1 поток: makeQuery
* {...}
* takeResponse...
* 2 поток: giveResponse
*
* @author Vassaev A.V.
* @version 1.0
*/
public class InfoBase<Q, R> {
public InfoBase() {
}
private final Map<String, Q> qt = new HashMap<String, Q>();//Запросы
private final Map<String, R> rt = new HashMap<String, R>();//Ответы
/**
* Создать запрос
*
* @param msg - сообщение
* @param key - ключ сообщения
* @throws SysException - ошибка создания запроса
*/
public void makeQuery(Q msg, String key) throws SysException {
synchronized (qt) {
if (qt.get(key) != null)
throw new SysException("The key is not unique");
qt.put(key, msg);
}
}
/**
* Дать ответ на запрос
*
* @param msg - сообщение
* @param key - ключ сообщения
* @throws ru.vassaev.core.exception.SysException
*
*/
public void giveResponse(R msg, String key) throws SysException {
Q q;
synchronized (qt) {
q = qt.get(key);
if (q == null)
throw new SysException("There is no query for this response");
}
synchronized (rt) {
if (rt.get(key) != null)
throw new SysException("The key is not unique");
rt.put(key, msg);
}
synchronized (q) {
q.notify();
}
}
/**
* Забрать ответ на запрос
*
* @param key - ключ запроса
* @return - результат запроса
* @throws SysException
*/
public R takeResponse(String key) throws SysException {
Q q;
synchronized (qt) {
q = qt.get(key);
if (q == null)
throw new SysException("There is no query for this response");
}
R r = null;
try {
synchronized (rt) {
r = rt.remove(key);
return r;
}
} finally {
if (r != null)
synchronized (qt) {
qt.remove(key);
}
}
}
/**
* Забрать ответ на запрос (с ожиданием его появления)
*
* @param key
* @return
* @throws SysException
*/
public R takeResponseWithWait(String key) throws SysException {
Q q = null;
synchronized (qt) {
q = qt.get(key);
if (q == null)
throw new SysException("There is no query for this response");
}
R r = null;
try {
synchronized (q) {
do {
synchronized (rt) {
r = rt.remove(key);
}
if (r != null)
return r;
try {
q.wait();
} catch (InterruptedException ex) {
throw new SysException(ex);
}
if (qt.get(key) == null) {
return null;
}
} while (true);
}
} finally {
if (r != null) {
synchronized (qt) {
qt.remove(key);
}
}
}
}
/**
* Забрать ответ на запрос (с ожиданием его появления)
*
* @param key
* @param timeout
* @return
* @throws SysException
*/
public R takeResponseWithWait(String key, long timeout) throws SysException {
Q q;
synchronized (qt) {
q = qt.get(key);
if (q == null)
throw new SysException("There is no query for this response");
}
R r = null;
try {
long to = timeout / 10;
long from = System.currentTimeMillis();
long to_time = from + timeout;
//long from = System.currentTimeMillis();
synchronized (q) {
synchronized (rt) {
r = rt.remove(key);
if (r != null)
return r;
}
//to_time > System.currentTimeMillis()
while (to_time > System.currentTimeMillis()) {
try {
q.wait(to);
} catch (InterruptedException ex) {
throw new SysException(ex);
}
if (qt.get(key) == null)
return null;
synchronized (rt) {
r = rt.remove(key);
if (r != null)
return r;
}
}
}
return null;
} finally {
if (r != null) {
synchronized (qt) {
qt.remove(key);
}
}
}
}
public R takeResponseWithWait(String key, long timeout, long th, ITaskAPI ta, long id_processor) throws SysException {
Q q;
synchronized (qt) {
q = qt.get(key);
if (q == null)
throw new SysException("There is no query for this response");
}
R r = null;
try {
long to = timeout / 10;
long from = System.currentTimeMillis();
Date dt_to = new Date(System.currentTimeMillis() + timeout);
//long from = System.currentTimeMillis();
synchronized (q) {
ta.log(id_processor, th, "from = " + new Date(from) + " - " + key);
ta.log(id_processor, th, "from + timeout = " + new Date(from + timeout) + " - " + key);
//from + timeout > System.currentTimeMillis()
synchronized (rt) {
r = rt.remove(key);
if (r != null) {
ta.log(id_processor, th, "-----0-----" + key + " - " + new Date());
return r;
}
}
while (dt_to.after(new Date())) {
try {
q.wait(to);
ta.log(id_processor, th, "-----3-----" + key + " - " + new Date());
} catch (InterruptedException ex) {
throw new SysException(ex);
}
if (qt.get(key) == null) {
ta.log(id_processor, th, "-----1-----" + key + " - " + new Date());
return null;
}
synchronized (rt) {
r = rt.remove(key);
if (r != null) {
ta.log(id_processor, th, "-----0-----" + key + " - " + new Date());
return r;
}
}
}
}
ta.log(id_processor, th, "-----2-----" + key);
ta.log(id_processor, th, "System.currentTimeMillis() = " + new Date(System.currentTimeMillis()) + " - " + key);
return null;
} finally {
if (r != null) {
synchronized (qt) {
qt.remove(key);
}
}
}
}
/**
* Отменить запрос
*
* @param key - ключ запроса
*/
public void revokeQuery(String key) {
synchronized(qt) {
rt.remove(key);
qt.remove(key);
}
}
/**
* Отменить ответ
*
* @param key - ключ запроса
*/
public void revokeResponse(String key) {
synchronized(qt) {
rt.remove(key);
}
}
}