Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.n3r.diamond.client.impl.DiamondRemoteChecker Maven / Gradle / Ivy
package org.n3r.diamond.client.impl;
import com.google.common.base.Optional;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.MoreExecutors;
import org.apache.commons.lang3.StringUtils;
import org.n3r.diamond.client.DiamondAxis;
import org.n3r.diamond.client.DiamondListener;
import org.n3r.diamond.client.DiamondStone;
import org.n3r.diamond.client.cache.DiamondCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
class DiamondRemoteChecker {
private final DiamondCache diamondCache;
private Logger log = LoggerFactory.getLogger(DiamondRemoteChecker.class);
private Cache> contentCache = CacheBuilder.newBuilder()
.expireAfterAccess(15, TimeUnit.MINUTES)
.maximumSize(10000)
.build();
private volatile DiamondAllListener diamondAllListener = new DiamondAllListener();
private DiamondHttpClient diamondHttpClient;
private final DiamondManagerConf managerConfig;
private final DiamondSubscriber diamondSubscriber;
public DiamondRemoteChecker(DiamondSubscriber diamondSubscriber,
DiamondManagerConf managerConfig,
DiamondCache diamondCache,
DiamondHttpClient diamondHttpClient) {
this.diamondSubscriber = diamondSubscriber;
this.managerConfig = managerConfig;
this.diamondCache = diamondCache;
this.diamondHttpClient = diamondHttpClient;
}
public void addDiamondListener(DiamondAxis diamondAxis, DiamondListener diamondListener) {
diamondAllListener.addDiamondListener(diamondAxis, diamondListener);
}
public void removeDiamondListener(DiamondAxis diamondAxis, DiamondListener diamondListener) {
diamondAllListener.removeDiamondListener(diamondAxis, diamondListener);
}
public void shutdown() {
diamondHttpClient.shutdown();
}
public void checkRemote() {
Set updateDataIdGroupPairs = checkUpdateDataIds(managerConfig.getReceiveWaitTime());
if (null == updateDataIdGroupPairs || updateDataIdGroupPairs.size() == 0) {
return;
}
for (String freshDataIdGroupPair : updateDataIdGroupPairs) {
int middleIndex = freshDataIdGroupPair.indexOf(Constants.WORD_SEPARATOR);
if (middleIndex == -1) continue;
String freshDataId = freshDataIdGroupPair.substring(0, middleIndex);
String freshGroup = freshDataIdGroupPair.substring(middleIndex + 1);
DiamondAxis diamondAxis = DiamondAxis.makeAxis(freshGroup, freshDataId);
DiamondMeta diamondMeta = diamondSubscriber.getCachedMeta(diamondAxis);
receiveDiamondContent(diamondMeta);
}
}
private void receiveDiamondContent(final DiamondMeta diamondMeta) {
try {
retrieveRemoteAndInvokeListeners(diamondMeta);
} catch (Exception e) {
log.error("retrieveRemoteAndInvokeListeners error", e.getMessage());
}
}
private void retrieveRemoteAndInvokeListeners(DiamondMeta diamondMeta) {
String diamondContent = retrieveRemote(diamondMeta.getDiamondAxis(),
managerConfig.getReceiveWaitTime(), false);
// if (null == diamondContent) return;
if (null == diamondAllListener) {
log.warn("null == configInfoListenable");
return;
}
onDiamondChanged(diamondMeta, diamondContent);
}
Future onDiamondChanged(final DiamondMeta diamondMeta, final String content) {
final DiamondStone diamondStone = new DiamondStone();
diamondStone.setContent(content);
diamondStone.setDiamondAxis(diamondMeta.getDiamondAxis());
diamondMeta.incSuccCounterAndGet();
Callable command = new Callable() {
public Object call() {
try {
diamondSubscriber.saveSnapshot(diamondStone.getDiamondAxis(), content);
diamondAllListener.accept(diamondStone);
return diamondCache.updateDiamondCacheOnChange(diamondStone.getDiamondAxis(), content);
} catch (Throwable t) {
log.error("onDiamondChanged {} with error {}", diamondMeta.getDiamondAxis(), t.getMessage());
}
return null;
}
};
ExecutorService executor = diamondAllListener.getExecutor();
if (executor == null) executor = MoreExecutors.sameThreadExecutor();
return executor.submit(command);
}
String retrieveRemote(DiamondAxis diamondAxis, long timeout, boolean useContentCache) {
diamondSubscriber.start();
if (useContentCache) {
Optional optional = contentCache.getIfPresent(diamondAxis);
if (optional != null) return optional.orNull();
}
long costTime = 0;
String uri = getUriString(diamondAxis);
// log.info(uri); // /diamond-server/content?dataId=res&group=poet.base
int totalRetryTimes = managerConfig.getRetrieveDataRetryTimes();
int triedTimes = 0;
Exception lastException = null; // for reduce logs
int lastHttpStatus = -1;
while (0 == timeout || timeout > costTime) {
if (triedTimes > 0) managerConfig.rotateToNextDomain(diamondHttpClient);
if (triedTimes > totalRetryTimes + 1) {
log.warn("reached the max retry times");
break;
}
if (triedTimes > 0 )
log.info("retrieve config,try {} times with costTime {}", triedTimes, costTime);
++triedTimes;
long onceTimeOut = getOnceTimeOut(costTime, timeout);
costTime += onceTimeOut;
try {
DiamondMeta diamondMeta = diamondSubscriber.getCachedMeta(diamondAxis);
DiamondHttpClient.GetDiamondResult getDiamondResult;
getDiamondResult = diamondHttpClient.getDiamond(uri, useContentCache, diamondMeta, onceTimeOut);
int httpStatus = getDiamondResult.getHttpStatus();
switch (httpStatus) {
case Constants.SC_OK:
return onSuccess(diamondAxis, diamondMeta, getDiamondResult);
case Constants.SC_NOT_MODIFIED:
return onNotModified(diamondAxis, diamondMeta, getDiamondResult);
case Constants.SC_NOT_FOUND:
log.warn("{} not found", diamondAxis);
diamondMeta.setMd5(Constants.NULL);
diamondSubscriber.removeSnapshot(diamondAxis);
diamondCache.removeCacheSnapshot(diamondAxis);
contentCache.put(diamondAxis, Optional.absent());
return null;
default: {
if (httpStatus != lastHttpStatus) {
log.warn("{}: HTTP State: {} : {} ", diamondAxis, httpStatus, diamondHttpClient.getState());
lastHttpStatus = httpStatus;
}
}
}
} catch (Exception e) {
if (!isMessageSameExeption(e, lastException)) {
log.error("{}: http error:{}", diamondAxis, e.getMessage());
lastException = e;
}
}
}
throw new RuntimeException("get config ," + diamondAxis + ", timeout=" + timeout);
}
private Set checkUpdateDataIds(long timeout) {
if (MockDiamondServer.isTestMode()) return null;
long costTime = 0;
String probeUpdateString = diamondSubscriber.createProbeUpdateString();
if (StringUtils.isBlank(probeUpdateString)) return null;
int lastHttpStatus = -1; // for reduce logs
Exception lastException = null;
while (0 == timeout || timeout > costTime) {
if (costTime > 0) managerConfig.rotateToNextDomain(diamondHttpClient);
long onceTimeOut = getOnceTimeOut(costTime, timeout);
costTime += onceTimeOut;
try {
DiamondHttpClient.CheckResult checkResult;
checkResult = diamondHttpClient.checkUpdateDataIds(probeUpdateString, onceTimeOut);
int httpStatus = checkResult.getHttpStatus();
switch (httpStatus) {
case Constants.SC_OK:
return checkResult.getUpdateDataIdsInBody();
default:
if (httpStatus != lastHttpStatus) {
log.warn("get changed DataID list response HTTP State: " + httpStatus);
lastHttpStatus = httpStatus;
}
}
} catch (NoNameServerAvailableException e) {
log.warn("checkUpdateDataIds error {}", e.getMessage());
break;
} catch (Exception e) {
if (!isMessageSameExeption(e, lastException)){
log.warn("checkUpdateDataIds error {}", e.getMessage());
lastException = e;
}
}
}
throw new RuntimeException("get changed dataId list to "
+ managerConfig.getDomainName() + " timeout " + timeout);
}
private boolean isMessageSameExeption(Exception e1, Exception e2) {
if (e1 == e2) return true;
if (e1 == null) return false;
if (e2 == null) return false;
return e1.getMessage().equals(e2.getMessage());
}
private String onSuccess(DiamondAxis diamondAxis, DiamondMeta diamondMeta,
DiamondHttpClient.GetDiamondResult httpMethod) {
String diamondContent = httpMethod.getResponseContent();
if (!DiamondUtils.checkMd5(diamondContent, httpMethod.getMd5())) {
throw new RuntimeException("MD5 check error for DataID="
+ diamondAxis.getDataId() + ", content=" + diamondContent + ", md5=" + httpMethod.getMd5());
}
String lastModified = httpMethod.getLastModified();
diamondMeta.setMd5(httpMethod.getMd5());
diamondMeta.setLastModifiedHeader(lastModified);
changeSpacingInterval(httpMethod);
contentCache.put(diamondAxis, Optional.fromNullable(diamondContent));
// log.debug("received {}, content={}", diamondAxis, diamondContent);
return diamondContent;
}
long getOnceTimeOut(long costTime, long totalTimeout) {
long onceTimeOut = this.managerConfig.getOnceTimeout();
long remainTime = totalTimeout - costTime;
if (onceTimeOut > remainTime) onceTimeOut = remainTime;
return onceTimeOut;
}
private String onNotModified(DiamondAxis diamondAxis, DiamondMeta diamondMeta,
DiamondHttpClient.GetDiamondResult httpMethod) {
String md5 = httpMethod.getMd5();
if (!diamondMeta.getMd5().equals(md5)) {
String lastMd5 = diamondMeta.getMd5();
diamondMeta.setMd5(Constants.NULL);
diamondMeta.setLastModifiedHeader(Constants.NULL);
throw new RuntimeException("MD5 checked error," + diamondAxis
+ " last md5=" + lastMd5 + ", current md5=" + md5);
}
diamondMeta.setMd5(md5);
changeSpacingInterval(httpMethod);
log.info("{} not modified", diamondAxis);
return null;
}
void changeSpacingInterval(DiamondHttpClient.GetDiamondResult httpMethod) {
int pollingIntervalTime = httpMethod.getPollingInterval();
if (pollingIntervalTime > 0) managerConfig.setPollingInterval(pollingIntervalTime);
}
String getUriString(DiamondAxis diamondAxis) {
StringBuilder uriBuilder = new StringBuilder();
uriBuilder.append(Constants.HTTP_URI_FILE)
.append("?" + Constants.DATA_ID + "=" + diamondAxis.getDataId())
.append("&" + Constants.GROUP + "=" + diamondAxis.getGroup());
return uriBuilder.toString();
}
}