package jane.core;
import java.lang.management.ManagementFactory;
import java.util.concurrent.ConcurrentLinkedQueue;
import jane.core.Procedure.IndexLock;
public final class ProcThread extends Thread
{
private static final ConcurrentLinkedQueue<ProcThread> _procThreads = new ConcurrentLinkedQueue<>(); // 当前运行的全部事务线程. 用于判断是否超时
private static volatile long _interruptCount; // 事务被打断的次数统计
final IndexLock[] locks = new IndexLock[Const.maxLockPerProcedure]; // 当前线程已经加过的锁
int lockCount; // 当前进程已经加过锁的数量
final SContext sctx = new SContext(); // 当前线程上的安全修改的上下文
volatile Procedure proc; // 当前运行的事务
volatile long beginTime; // 当前/上个事务运行的起始时间. 用于判断是否超时
final int[] versions = new int[Const.maxLockPerProcedure]; // 当前线程已经加过的锁版本号(只在需要时临时设置,这里只是为了避免反复分配)
public ProcThread(String name, Runnable r)
{
super(r, name != null ? name : "ProcThread");
_procThreads.add(this);
}
/*
volatile IndexLock nowLock;
private static boolean mayDeadLock0(java.util.ArrayList<ProcThread> otherLockingThreads, IndexLock checkLock, IndexLock nowLock)
{
for(ProcThread pt : otherLockingThreads)
{
if(pt.nowLock != checkLock) continue;
IndexLock[] ls = pt.locks;
for(int j = pt.lockCount - 1; j >= 0; --j)
{
IndexLock lk = ls[j];
if(lk != null && lk != checkLock && (lk == nowLock || mayDeadLock0(otherLockingThreads, lk, nowLock)))
return true;
}
}
return false;
}
private boolean mayDeadLock()
{
if(lockCount < 1) return false;
java.util.ArrayList<ProcThread> otherLockingThreads = new java.util.ArrayList<>();
for(ProcThread pt : _procThreads)
{
if(pt != this && pt.nowLock != null)
otherLockingThreads.add(pt);
}
IndexLock[] ls = locks;
IndexLock nl = nowLock;
for(int i = lockCount - 1; i >= 0; --i)
{
if(mayDeadLock0(otherLockingThreads, ls[i], nl))
return true;
}
return false;
}
void safeLock(IndexLock lock) throws InterruptedException
{
nowLock = lock;
if(!lock.tryLock())
{
if(mayDeadLock())
Procedure.redo();
lock.lockInterruptibly();
}
nowLock = null;
locks[++lockCount] = lock;
}
void safeLock(IndexLock lock, int i) throws InterruptedException
{
lockCount = i;
nowLock = lock;
if(!lock.tryLock())
{
if(mayDeadLock())
Procedure.redo();
lock.lockInterruptibly();
}
nowLock = null;
locks[i] = lock;
lockCount = i + 1;
}
//*/
/**
* 获取事务被打断的次数统计
*/
public static long getInterruptCount()
{
return _interruptCount;
}
static
{
if(!Const.debug && Const.deadlockCheckInterval > 0)
{
NetManager.scheduleAtFixedRate(Const.deadlockCheckInterval, Const.deadlockCheckInterval, new Runnable()
{
@Override
public void run()
{
try
{
long[] tids = null;
boolean foundDeadlock = false;
long now = System.currentTimeMillis();
long procTimeout = (long)Const.procedureTimeout * 1000;
long procDeadlockTimeout = (long)Const.procedureDeadlockTimeout * 1000;
long procTimoutMin = Math.min(procTimeout, procDeadlockTimeout);
for(ProcThread pt : _procThreads)
{
if(pt.isAlive())
{
Procedure p = pt.proc;
if(p != null && now - pt.beginTime > procTimoutMin)
{
synchronized(p)
{
if(p == pt.proc)
{
long timeout = now - pt.beginTime;
if(timeout > procTimeout)
{
StringBuilder sb = new StringBuilder(2000);
sb.append("procedure({}) in {} interrupted for timeout ({} ms): sid={}\n");
for(StackTraceElement ste : pt.getStackTrace())
sb.append("\tat ").append(ste).append('\n');
Log.log.error(sb.toString(), p.getClass().getName(), pt, timeout, p.getSid());
++_interruptCount;
pt.interrupt();
}
else if(timeout > procDeadlockTimeout)
{
if(!foundDeadlock)
{
foundDeadlock = true;
tids = ManagementFactory.getThreadMXBean().findDeadlockedThreads();
}
if(tids != null)
{
long tid = pt.getId();
for(int i = tids.length - 1; i >= 0; --i)
{
if(tids[i] == tid)
{
StringBuilder sb = new StringBuilder(2000);
sb.append("procedure({}) in {} interrupted for deadlock timeout({} ms): sid={}\n");
for(StackTraceElement ste : pt.getStackTrace())
sb.append("\tat ").append(ste).append('\n');
Log.log.error(sb.toString(), p.getClass().getName(), pt, timeout, p.getSid());
++_interruptCount;
pt.interrupt();
break;
}
}
}
}
}
}
}
}
else
_procThreads.remove(pt);
}
}
catch(Throwable e)
{
Log.log.error("procedure timeout fatal exception:", e);
}
}
});
}
}
}