/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.web.analytics;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.engine.view.ExecutionLogMode;
import com.opengamma.engine.view.client.ViewClient;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.tuple.Pair;
/**
* Listens for changes to viewports and updates the logging configuration in the {@link ViewClient}.
*/
/* package */ class LoggingViewportListener implements ViewportListener {
private static final Logger s_logger = LoggerFactory.getLogger(LoggingViewportListener.class);
private final ViewClient _viewClient;
private final Map<Pair<String, ValueSpecification>, Integer> _refCounts = Maps.newHashMap();
/* package */ LoggingViewportListener(ViewClient viewClient) {
ArgumentChecker.notNull(viewClient, "viewClient");
_viewClient = viewClient;
}
@Override
public void viewportCreated(ViewportDefinition viewportDef, GridStructure gridStructure) {
if (viewportDef.enableLogging()) {
enableLogging(viewportDef, gridStructure);
}
}
private void enableLogging(ViewportDefinition viewportDef, GridStructure gridStructure) {
Set<Pair<String, ValueSpecification>> newVals = Sets.newHashSet();
for (GridCell cell : viewportDef) {
Pair<String, ValueSpecification> valueSpec = gridStructure.getValueSpecificationForCell(cell.getRow(),
cell.getColumn());
if (valueSpec == null) {
continue;
}
Integer refCount = _refCounts.get(valueSpec);
Integer newRefCount;
if (refCount == null) {
newRefCount = 1;
newVals.add(valueSpec);
} else {
newRefCount = refCount + 1;
}
_refCounts.put(valueSpec, newRefCount);
}
s_logger.debug("Setting log mode to FULL for {}", newVals);
_viewClient.setMinimumLogMode(ExecutionLogMode.FULL, newVals);
}
@Override
public void viewportUpdated(ViewportDefinition currentDef, ViewportDefinition newDef, GridStructure gridStructure) {
if (currentDef.enableLogging() && newDef.enableLogging()) {
// logging enabled for both versions of the viewport
Set<GridCell> currentCells = Sets.newHashSet(currentDef.iterator());
Set<GridCell> newCells = Sets.newHashSet(newDef.iterator());
Set<GridCell> cellsRemoved = Sets.difference(currentCells, newCells);
Set<GridCell> cellsAdded = Sets.difference(newCells, currentCells);
enableLogging(targetsFor(cellsAdded.iterator(), gridStructure));
disableLogging(targetsFor(cellsRemoved.iterator(), gridStructure));
} else if (!currentDef.enableLogging() && newDef.enableLogging()) {
// no logging for current viewport, increase log level for all cells
enableLogging(targetsFor(newDef.iterator(), gridStructure));
} else if (currentDef.enableLogging() && !newDef.enableLogging()) {
// reduce logging level for all cells in current viewport
disableLogging(targetsFor(currentDef.iterator(), gridStructure));
}
}
private Set<Pair<String, ValueSpecification>> targetsFor(Iterator<GridCell> cellIterator, GridStructure gridStructure) {
Set<Pair<String, ValueSpecification>> targets = Sets.newHashSet();
while (cellIterator.hasNext()) {
GridCell cell = cellIterator.next();
targets.add(gridStructure.getValueSpecificationForCell(cell.getRow(), cell.getColumn()));
}
return targets;
}
@Override
public void viewportDeleted(ViewportDefinition viewportDef, GridStructure gridStructure) {
if (viewportDef.enableLogging()) {
disableLogging(targetsFor(viewportDef.iterator(), gridStructure));
}
}
/**
* Increments the ref count for the value specs and returns the set of specs whose ref count was previously zero.
* @param targets The referenced specs
*/
private void enableLogging(Set<Pair<String, ValueSpecification>> targets) {
Set<Pair<String, ValueSpecification>> newlyReferenced = Sets.newHashSet();
for (Pair<String, ValueSpecification> target : targets) {
Integer refCount = _refCounts.get(target);
Integer newRefCount;
if (refCount == null) {
newRefCount = 1;
newlyReferenced.add(target);
} else {
newRefCount = refCount + 1;
}
_refCounts.put(target, newRefCount);
}
_viewClient.setMinimumLogMode(ExecutionLogMode.FULL, newlyReferenced);
}
/**
* Decrements the ref count for the value specs and returns the set of specs whose ref count is now zero.
* @param targets The referenced specs
*/
private void disableLogging(Set<Pair<String, ValueSpecification>> targets) {
Set<Pair<String, ValueSpecification>> dereferenced = Sets.newHashSet();
for (Pair<String, ValueSpecification> target : targets) {
Integer refCount = _refCounts.get(target);
Integer newRefCount;
if (refCount != null) {
if (refCount.equals(1)) {
_refCounts.remove(target);
dereferenced.add(target);
} else {
newRefCount = refCount - 1;
_refCounts.put(target, newRefCount);
}
}
}
s_logger.debug("Setting log mode to INDICATORS for {}", dereferenced);
_viewClient.setMinimumLogMode(ExecutionLogMode.INDICATORS, dereferenced);
}
}