blob: 5b573a8a197e29837b30b7f016a40a487a7ece2c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018-2019 Aston University.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 3.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-3.0
*
* Contributors:
* Antonio Garcia-Dominguez - initial API and implementation
******************************************************************************/
package org.hawk.timeaware.graph;
import java.io.File;
import java.time.Instant;
import org.hawk.core.IConsole;
import org.hawk.core.ICredentialsStore;
import org.hawk.core.IVcsManager;
import org.hawk.core.VcsCommit;
import org.hawk.core.VcsRepositoryDelta;
import org.hawk.core.graph.IGraphTransaction;
import org.hawk.core.graph.timeaware.ITimeAwareGraphDatabase;
import org.hawk.core.runtime.BaseModelIndexer;
import org.hawk.timeaware.graph.VCSManagerIndex.RepositoryNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Indexes all revisions of the models in the repository. Requires using
* backends and locations that can handle full history (currently Greycat +
* SVN).
*/
public class TimeAwareIndexer extends BaseModelIndexer {
private static final Logger LOGGER = LoggerFactory.getLogger(TimeAwareIndexer.class);
public TimeAwareIndexer(String name, File parentFolder, ICredentialsStore credStore, IConsole c) {
super(name, parentFolder, credStore, c);
}
@Override
protected void resetRepository(String repoURL) {
// nothing to do - we keep track of repository information in the graph
}
@Override
protected boolean synchronise(IVcsManager vcsManager) {
if (!(graph instanceof ITimeAwareGraphDatabase)) {
LOGGER.error("This indexer requires a time-aware backend, aborting");
return false;
}
ITimeAwareGraphDatabase taGraph = (ITimeAwareGraphDatabase)graph;
String lastRev;
try {
taGraph.setTime(0);
lastRev = getLastIndexedRevision(vcsManager);
} catch (Exception e) {
LOGGER.error("Could not fetch the last indexed revision", e);
return false;
}
boolean success = true;
try {
final String currentRevision = vcsManager.getCurrentRevision();
if (!currentRevision.equals(lastRev)) {
latestUpdateFoundChanges = true;
VcsRepositoryDelta delta = vcsManager.getDelta(lastRev, currentRevision);
for (VcsCommit commit : delta.getCommits()) {
// Commits might be only milliseconds apart in automated processes
final Instant instant = commit.getJavaDate().toInstant();
final long epochMillis = instant.getEpochSecond() * 1000 + instant.getNano() / 1_000_000;
// Do not allow anyone else to change the time while we are manipulating the graph
synchronized(taGraph) {
taGraph.setTime(epochMillis);
/*
* TODO: allow for fixing unresolved proxies in previous versions? Might make
* sense if we forgot to add a metamodel in a previous version.
*/
success = success && synchroniseFiles(commit.getRevision(), vcsManager, commit.getItems());
console.println(String.format("Index revision %s (timepoint %d) of %s",
commit.getRevision(), epochMillis, commit.getDelta().getManager().getLocation()));
setIndexedRevision(vcsManager, commit);
}
}
}
} catch (Exception e) {
LOGGER.error("Failed to synchronise repository " + vcsManager.getLocation(), e);
return false;
} finally {
synchronized (taGraph) {
taGraph.setTime(0);
}
}
return success;
}
protected String getLastIndexedRevision(IVcsManager vcsManager) throws Exception {
String lastRev;
try (IGraphTransaction tx = graph.beginTransaction()) {
VCSManagerIndex vcsIndex = new VCSManagerIndex((ITimeAwareGraphDatabase) graph);
RepositoryNode repoNode = vcsIndex.getOrCreateRepositoryNode(vcsManager.getLocation());
lastRev = repoNode.getLatest().getRevision();
tx.success();
}
return lastRev;
}
protected void setIndexedRevision(IVcsManager vcsManager, VcsCommit commit) throws Exception {
try (IGraphTransaction tx = graph.beginTransaction()) {
VCSManagerIndex vcsIndex = new VCSManagerIndex((ITimeAwareGraphDatabase) graph);
RepositoryNode repoNode = vcsIndex.getOrCreateRepositoryNode(vcsManager.getLocation());
repoNode.setRevision(commit.getRevision());
repoNode.setMessage(commit.getMessage());
tx.success();
}
}
}