edu.stanford.protege.webprotege.index.impl.IndexUpdater Maven / Gradle / Ivy
The newest version!
package edu.stanford.protege.webprotege.index.impl;
import com.google.common.base.Stopwatch;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.graph.Graph;
import com.google.common.graph.GraphBuilder;
import edu.stanford.protege.webprotege.change.OntologyChange;
import edu.stanford.protege.webprotege.index.DependentIndex;
import edu.stanford.protege.webprotege.index.IndexUpdatingService;
import edu.stanford.protege.webprotege.inject.ProjectSingleton;
import edu.stanford.protege.webprotege.common.ProjectId;
import edu.stanford.protege.webprotege.revision.Revision;
import edu.stanford.protege.webprotege.revision.RevisionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import java.lang.management.ManagementFactory;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
/**
* Matthew Horridge
* Stanford Center for Biomedical Informatics Research
* 2019-08-09
*/
@ProjectSingleton
public class IndexUpdater {
private static final Logger logger = LoggerFactory.getLogger(IndexUpdater.class);
@Nonnull
private final RevisionManager revisionManager;
private final Collection indexes;
@Nonnull
private final ExecutorService indexUpdaterService;
@Nonnull
private final ProjectId projectId;
private boolean builtIndexes = false;
@Inject
public IndexUpdater(@Nonnull RevisionManager revisionManager,
@Nonnull Set indexes,
@Nonnull @IndexUpdatingService ExecutorService indexUpdaterService,
@Nonnull ProjectId projectId) {
this.revisionManager = checkNotNull(revisionManager);
this.indexes = checkNotNull(indexes);
this.indexUpdaterService = checkNotNull(indexUpdaterService);
this.projectId = checkNotNull(projectId);
}
private Multimap getRankedIndexes() {
var graph = GraphBuilder.directed().allowsSelfLoops(false).build();
for(var index : indexes) {
graph.addNode(index);
if(index instanceof DependentIndex) {
var dependentIndex = (DependentIndex) index;
dependentIndex.getDependencies()
.stream()
.map(dep -> (UpdatableIndex) dep)
.forEach(dependency -> graph.putEdge(index, dependency));
}
}
var rankMap = HashMultimap.create();
for(var index : indexes) {
var rank = getRank(index, graph);
rankMap.put(rank, index);
}
return rankMap;
}
private int getRank(UpdatableIndex index, Graph depGraph) {
int depth = 0;
for(var successor : depGraph.successors(index)) {
int successorDepth = 1 + getRank(successor, depGraph);
if(successorDepth > depth) {
depth = successorDepth;
}
}
return depth;
}
public synchronized void buildIndexes() {
if(builtIndexes) {
return;
}
builtIndexes = true;
var revisions = revisionManager.getRevisions();
var revisionChanges = revisions.stream()
.map(Revision::getChanges)
.collect(toImmutableList());
updateIndexesWithRevisions(revisionChanges);
}
private synchronized void updateIndexesWithRevisions(ImmutableList> revisions) {
var rankedIndexes = getRankedIndexes();
var ranks = rankedIndexes.keySet().size();
for(var rank = 0; rank < ranks; rank++) {
var rankIndexes = rankedIndexes.get(rank);
buildIndexesWithRevisions(rank, rankIndexes, revisions);
}
}
private void buildIndexesWithRevisions(int rank,
Collection indexes,
ImmutableList> revisions) {
try {
var stopwatch = Stopwatch.createStarted();
var countDownLatch = new CountDownLatch(indexes.size());
indexes.forEach(index -> buildIndex(rank, index, revisions, countDownLatch));
countDownLatch.await();
stopwatch.stop();
logger.info("{} Built indexes in {} ms",
projectId,
stopwatch.elapsed()
.toMillis());
} catch(InterruptedException e) {
logger.error("{} Interrupted while building indexes", projectId);
}
}
private void buildIndex(int rank,
@Nonnull UpdatableIndex index,
@Nonnull ImmutableList> revisions,
@Nonnull CountDownLatch countDownLatch) {
var updaterTask = new IndexUpdaterTask(projectId, rank, index, revisions, countDownLatch);
indexUpdaterService.submit(updaterTask);
}
public synchronized void updateIndexes(ImmutableList changes) {
updateIndexesWithRevisions(ImmutableList.of(changes));
}
private static class IndexUpdaterTask implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(IndexUpdaterTask.class);
private final ProjectId projectId;
private final int rank;
@Nonnull
private final UpdatableIndex index;
@Nonnull
private final ImmutableList> revisions;
@Nonnull
private final CountDownLatch countDownLatch;
public IndexUpdaterTask(ProjectId projectId,
int rank,
UpdatableIndex index,
@Nonnull ImmutableList> revisions,
@Nonnull CountDownLatch countDownLatch) {
this.projectId = checkNotNull(projectId);
this.rank = rank;
this.index = checkNotNull(index);
this.revisions = checkNotNull(revisions);
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
var stopwatch = Stopwatch.createStarted();
var indexName = index.getClass().getSimpleName();
var threadMxBean = ManagementFactory.getThreadMXBean();
var cpu0 = threadMxBean.getCurrentThreadCpuTime();
revisions.forEach(index::applyChanges);
countDownLatch.countDown();
var cpu1 = threadMxBean.getCurrentThreadCpuTime();
var cpuTimeMs = (cpu1 - cpu0) / (1_000_000);
stopwatch.stop();
logger.info("{} Built {} in {} ms of user-time ({} ms wall-clock)",
projectId,
indexName,
cpuTimeMs,
stopwatch.elapsed()
.toMillis());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy