// In browser interface we add a custom value to the cache key, so BI caches and Non-Bi caches differ (B000059DA)
if (status.isBrowserInterface()) {
status._currentCacheKey = status._currentCacheKey + "###BROWSER-INTERFACE";
}
WGDatabase db = this.getTMLContext().content().getDatabase();
// Look if the current cache is in evaluation right now, wait for 10 seconds
int sleepTimes = 0;
String cacheLockKey = buildCacheLockKey();
int waitTimeout = 60;
try {
waitTimeout = Integer.parseInt(getWaittimeout());
}
catch (NumberFormatException e) {
addWarning("Cannot parse waittimeout as number: " + getWaittimeout());
}
if (currentlyEvaluatedCaches.containsKey(cacheLockKey)) {
// If we are allowed to serve stale data while the cache processes, we serve the current content of the cache
boolean serveStaleData = db.getBooleanAttribute(WGACore.DBATTRIB_WEBTMLCACHE_SERVESTALEDATA, true);
if (serveStaleData) {
String content = null;
try {
content = getCore().getWebTMLCache().getCache(db.getDbReference(), status._currentCacheId, status._currentCacheKey, new Date(Long.MIN_VALUE));
}
catch (CacheException e) {
getTMLContext().getlog().error("Exception retrieving WebTML cache data for key " + getTMLContext().db().getDbReference() + "/" + status._currentCacheId + "/" + status._currentCacheKey, e);
}
if (content != null) {
// Tell all ranges above us to have a cache latency of 1 minute, so cached stale data is updated after this time
Range.Status ancestor = status;
while ((ancestor = (Range.Status) ancestor.getAncestorTag(Range.class)) != null) {
ancestor.cacheLatency = 1;
}
status._currentCacheKey = null;
status._currentCacheId = null;
status.servedStale = true;
this.setEvalBody(false);
this.setResult(content);
return;
}
}
// Else we wait until cache calculation is completed or we run into the timeout
while (currentlyEvaluatedCaches.containsKey(cacheLockKey)) {
Long cacheTime = (Long) currentlyEvaluatedCaches.get(cacheLockKey);
if( cacheTime != null ){
long cacheTimeout = cacheTime.longValue() + (1000 * 60 * 15);
if (System.currentTimeMillis() > cacheTimeout) {
log.warn("Former cache creation of key '" + status._currentCacheKey + "' took more than 15 minutes. Removing synchronisation lock now");
currentlyEvaluatedCaches.remove(cacheLockKey);
break;
}
}
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
}
sleepTimes++;
if (sleepTimes > waitTimeout) {
log.warn("Waiting for cache creation of key '" + cacheLockKey + "' timed out after " + waitTimeout + " second(s). Tag is canceled.");
this.addWarning("Waiting for cache creation of key '" + cacheLockKey + "' timed out after " + waitTimeout + " second(s). Tag is canceled.", true);
this.setEvalBody(false);
this.setCancelTag(true);
this.setResult("This section is currently recalculated. Please try again later.");
return;
}
}
}
currentlyEvaluatedCaches.put(cacheLockKey, new Long(System.currentTimeMillis()));
// Try to retrieve cache
Date testedDate = getCore().getDeployer().getLastChangedOrDeployed(db);
String content = null;
try {
content = getCore().getWebTMLCache().getCache(db.getDbReference(), status._currentCacheId, status._currentCacheKey, testedDate);
}
catch (CacheException e) {
getTMLContext().getlog().error("Exception retrieving WebTML cache data for key " + getTMLContext().db().getDbReference() + "/" + status._currentCacheId + "/" + status._currentCacheKey, e);
}