package com.dianping.pigeon.remoting.provider.process.statistics;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import com.dianping.pigeon.log.Logger;
import com.dianping.pigeon.config.ConfigManagerLoader;
import com.dianping.pigeon.log.LoggerLoader;
import com.dianping.pigeon.remoting.common.domain.InvocationRequest;
public class ProviderCapacityBucket implements Serializable {
private static final Logger logger = LoggerLoader.getLogger(ProviderCapacityBucket.class);
private AtomicInteger requests = new AtomicInteger();
private Map<Integer, AtomicInteger> totalRequestsInSecond = new ConcurrentHashMap<Integer, AtomicInteger>();
private Map<Integer, AtomicInteger> totalRequestsInMinute = new ConcurrentHashMap<Integer, AtomicInteger>();
//private Map<Integer, AtomicInteger> methodActives = new ConcurrentHashMap<Integer, AtomicInteger>();
public static final boolean enableMinuteStats = ConfigManagerLoader.getConfigManager().getBooleanValue(
"pigeon.providerstat.minute.enable", true);
public static void init() {
}
public ProviderCapacityBucket(String address) {
preFillData();
}
public void flowIn(InvocationRequest request) {
Calendar now = Calendar.getInstance();
requests.incrementAndGet();
int second = now.get(Calendar.SECOND);
incrementTotalRequestsInSecond(second);
if (enableMinuteStats) {
int minute = now.get(Calendar.MINUTE);
incrementTotalRequestsInMinute(minute);
}
}
public void flowOut(InvocationRequest request) {
requests.decrementAndGet();
}
public int getCurrentRequests() {
return requests.get();
}
public Map<Integer, AtomicInteger> getTotalRequestsInSecond() {
return totalRequestsInSecond;
}
public int getRequestsInCurrentSecond() {
Calendar cal = Calendar.getInstance();
int lastSecond = cal.get(Calendar.SECOND);
AtomicInteger counter = totalRequestsInSecond.get(lastSecond);
return counter != null ? counter.get() : 0;
}
public int getRequestsInLastSecond() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, -1);
int lastSecond = cal.get(Calendar.SECOND);
AtomicInteger counter = totalRequestsInSecond.get(lastSecond);
return counter != null ? counter.get() : 0;
}
public int getRequestsInSecond(int second) {
AtomicInteger counter = totalRequestsInSecond.get(second);
return counter != null ? counter.get() : 0;
}
public int getRequestsInLastMinute() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, -1);
int lastMinute = cal.get(Calendar.MINUTE);
lastMinute = lastMinute >= 0 ? lastMinute : lastMinute + 60;
AtomicInteger counter = totalRequestsInMinute.get(lastMinute);
return counter != null ? counter.get() : 0;
}
private void incrementTotalRequestsInSecond(int second) {
AtomicInteger counter = totalRequestsInSecond.get(second);
if (counter != null) {
counter.incrementAndGet();
} else {
logger.warn("Impossible case happended, second[" + second + "]'s request counter is null.");
}
}
private void incrementTotalRequestsInMinute(int minute) {
AtomicInteger counter = totalRequestsInMinute.get(minute);
if (counter != null) {
counter.incrementAndGet();
} else {
logger.warn("Impossible case happended, minute[" + minute + "]'s request counter is null.");
}
}
/**
* 重置过期的每秒请求数计数器
*/
public void resetRequestsInSecondCounter() {
int second = Calendar.getInstance().get(Calendar.SECOND);
int prev3Sec = second - 10;
for (int i = 1; i <= 30; i++) {
int prevSec = prev3Sec - i;
prevSec = prevSec >= 0 ? prevSec : prevSec + 60;
AtomicInteger counter = totalRequestsInSecond.get(prevSec);
if (counter != null) {
counter.set(0);
}
}
}
public void resetRequestsInMinuteCounter() {
if (enableMinuteStats) {
int min = Calendar.getInstance().get(Calendar.MINUTE);
int prev3Sec = min - 10;
for (int i = 1; i <= 30; i++) {
int prevSec = prev3Sec - i;
prevSec = prevSec >= 0 ? prevSec : prevSec + 60;
AtomicInteger counter = totalRequestsInMinute.get(prevSec);
if (counter != null) {
counter.set(0);
}
}
}
}
private void preFillData() {
for (int sec = 0; sec < 60; sec++) {
totalRequestsInSecond.put(sec, new AtomicInteger());
}
if (enableMinuteStats) {
for (int min = 0; min < 60; min++) {
totalRequestsInMinute.put(min, new AtomicInteger());
}
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("requests-current:").append(requests).append(",requests-currentsecond:")
.append(getRequestsInCurrentSecond()).append(",requests-lastsecond:").append(getRequestsInLastSecond())
.toString();
if (enableMinuteStats) {
sb.append(",requests-lastminute:").append(getRequestsInLastMinute());
}
return sb.toString();
}
}