package com.profiler.context; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; /** * 뭔가 복잡한 비동기 call trace시 객체 등록용으로 쓰자. * 근데 손좀봐야 될듯.뭔가 좀 구림. */ public class GlobalCallTrace { private static final long FLUSH_TIMEOUT = 120000L; // 2 minutes private static AtomicInteger timerId = new AtomicInteger(0); private ConcurrentMap trace = new ConcurrentHashMap(32); private AtomicInteger idGenerator = new AtomicInteger(0); private Timer timer = new Timer("GlobalCallTrace-Timer-" + timerId.getAndIncrement(), true); public int registerTraceObject(AsyncTrace asyncTrace) { // TODO 연관관계가 전달부분이 영 별로임. TimeoutTask timeoutTask = new TimeoutTask(trace, asyncTrace.getAsyncId()); asyncTrace.setTimeoutTask(timeoutTask); int id = put(asyncTrace); asyncTrace.setAsyncId(id); timer.schedule(timeoutTask, FLUSH_TIMEOUT); return id; } private int put(AsyncTrace asyncTrace) { int id = idGenerator.getAndIncrement(); trace.put(id, asyncTrace); return id; } public AsyncTrace getTraceObject(int asyncId) { return trace.get(asyncId); } public AsyncTrace removeTraceObject(int asyncId) { AsyncTrace asyncTrace = trace.remove(asyncId); if (asyncTrace != null) { boolean result = asyncTrace.fire(); if (!result) { // 이미 timeout된 asyncTrace임. return null; } } return asyncTrace; } private final class TimeoutTask extends TimerTask { private ConcurrentMap trace; private int id; // private final AsyncTrace asyncTrace; public TimeoutTask(ConcurrentMap trace, int id) { this.trace = trace; this.id = id; } @Override public void run() { AsyncTrace asyncTrace = trace.remove(id); if (asyncTrace != null) { asyncTrace.timeout(); } } } }