Skip to content

Commit

Permalink
Use a single cache removal strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Oct 28, 2020
1 parent a805c07 commit 67d5b4b
Showing 1 changed file with 18 additions and 111 deletions.
129 changes: 18 additions & 111 deletions daemon/src/main/java/org/jboss/fuse/mvnd/plugin/CliPluginRealmCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@
import java.io.IOException;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
Expand All @@ -40,13 +37,13 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import javax.enterprise.inject.Default;
import javax.inject.Named;
import javax.inject.Singleton;

import org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.eventspy.AbstractEventSpy;
Expand Down Expand Up @@ -115,7 +112,7 @@ public CacheKey(Plugin plugin, ClassLoader parentRealm, Map<String, ClassLoader>
}
}
this.parentRealm = parentRealm;
this.foreignImports = (foreignImports != null) ? foreignImports : Collections.<String, ClassLoader> emptyMap();
this.foreignImports = (foreignImports != null) ? foreignImports : Collections.emptyMap();
this.filter = dependencyFilter;

int hash = 17;
Expand Down Expand Up @@ -161,19 +158,17 @@ public boolean equals(Object o) {
}
}

interface RecordValidator {
void validateRecords();

ValidableCacheRecord newRecord(ClassRealm pluginRealm, List<Artifact> pluginArtifacts);
}
static class ValidableCacheRecord extends CacheRecord {

static abstract class ValidableCacheRecord extends CacheRecord {
private volatile boolean valid = true;

public ValidableCacheRecord(ClassRealm realm, List<Artifact> artifacts) {
super(realm, artifacts);
}

public abstract boolean isValid();
public boolean isValid() {
return valid;
}

public void dispose() {
ClassRealm realm = getRealm();
Expand All @@ -185,82 +180,10 @@ public void dispose() {
}
}

static class TimestampedRecordValidator implements RecordValidator {

@Override
public void validateRecords() {
}

@Override
public ValidableCacheRecord newRecord(ClassRealm realm, List<Artifact> artifacts) {
return new TimestampedCacheRecord(realm, artifacts);
}

}

static class TimestampedCacheRecord extends ValidableCacheRecord {

static class ArtifactTimestamp {
final Path path;
final FileTime lastModifiedTime;
final Object fileKey;

ArtifactTimestamp(Path path) {
this.path = path;
try {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
this.lastModifiedTime = attrs.lastModifiedTime();
this.fileKey = attrs.fileKey();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
ArtifactTimestamp that = (ArtifactTimestamp) o;
return path.equals(that.path) &&
Objects.equals(lastModifiedTime, that.lastModifiedTime) &&
Objects.equals(fileKey, that.fileKey);
}

@Override
public int hashCode() {
return Objects.hash(path, lastModifiedTime, fileKey);
}
}

Set<ArtifactTimestamp> timestamp;

public TimestampedCacheRecord(ClassRealm realm, List<Artifact> artifacts) {
super(realm, artifacts);
timestamp = current();
}

public boolean isValid() {
try {
return Objects.equals(current(), timestamp);
} catch (Exception e) {
return false;
}
}

private Set<ArtifactTimestamp> current() {
return getArtifacts().stream().map(Artifact::getFile)
.map(File::toPath)
.map(ArtifactTimestamp::new)
.collect(Collectors.toSet());
}
}

/**
* A {@link WatchService} with some methods to watch JARs associated with {@link WatchedCacheRecord}.
* A {@link RecordValidator} with some methods to watch JARs associated with {@link ValidableCacheRecord}.
*/
static class MultiWatcher implements RecordValidator {
static class RecordValidator {
private final WatchService watchService;

/**
Expand All @@ -275,7 +198,7 @@ static class MultiWatcher implements RecordValidator {
*/
private final Map<Path, Registration> registrationsByDir = new ConcurrentHashMap<>();

public MultiWatcher() {
public RecordValidator() {
try {
this.watchService = FileSystems.getDefault().newWatchService();
} catch (IOException e) {
Expand All @@ -286,7 +209,7 @@ public MultiWatcher() {
/**
* Watch the JARs associated with the given {@code record} for deletions and modifications.
*
* @param record the {@link WatchedCacheRecord} to watch
* @param record the {@link ValidableCacheRecord} to watch
*/
void add(ValidableCacheRecord record) {
record.getArtifacts().stream()
Expand Down Expand Up @@ -323,7 +246,7 @@ void add(ValidableCacheRecord record) {
/**
* Stopn watching the JARs associated with the given {@code record} for deletions and modifications.
*
* @param record the {@link WatchedCacheRecord} to stop watching
* @param record the {@link ValidableCacheRecord} to stop watching
*/
void remove(ValidableCacheRecord record) {
record.getArtifacts().stream()
Expand Down Expand Up @@ -368,7 +291,7 @@ public void validateRecords() {
synchronized (records) {
for (ValidableCacheRecord record : records) {
log.debug("Invalidating recorder of path {}", path);
((WatchedCacheRecord) record).valid = false;
record.valid = false;
remove(record);
}
records.clear();
Expand All @@ -383,7 +306,7 @@ public void validateRecords() {
if (records != null) {
synchronized (records) {
for (ValidableCacheRecord record : records) {
((WatchedCacheRecord) record).valid = false;
record.valid = false;
remove(record);
}
records.clear();
Expand All @@ -409,29 +332,14 @@ public Registration(WatchKey watchKey) {
}
}

@Override
public ValidableCacheRecord newRecord(ClassRealm pluginRealm, List<Artifact> pluginArtifacts) {
final ValidableCacheRecord result = new WatchedCacheRecord(pluginRealm, pluginArtifacts);
final ValidableCacheRecord result = new ValidableCacheRecord(pluginRealm, pluginArtifacts);
add(result);
return result;
}

}

static class WatchedCacheRecord extends ValidableCacheRecord {

private volatile boolean valid = true;

public WatchedCacheRecord(ClassRealm realm, List<Artifact> artifacts) {
super(realm, artifacts);
}

public boolean isValid() {
return valid;
}

}

private static final Logger log = LoggerFactory.getLogger(CliPluginRealmCache.class);
protected final Map<Key, ValidableCacheRecord> cache = new ConcurrentHashMap<>();
private final RecordValidator watcher;
Expand All @@ -446,6 +354,7 @@ public void onEvent(Object event) throws Exception {
/* Store the multiModuleProjectDirectory path */
multiModuleProjectDirectory = ((MavenExecutionRequest) event).getMultiModuleProjectDirectory().toPath();
} else if (event instanceof MavenExecutionResult) {
String rootUri = multiModuleProjectDirectory.toUri().toString();
/* Evict the entries refering to jars under multiModuleProjectDirectory */
final Iterator<Entry<Key, ValidableCacheRecord>> i = cache.entrySet().iterator();
while (i.hasNext()) {
Expand Down Expand Up @@ -474,9 +383,7 @@ public void onEvent(Object event) throws Exception {

public CliPluginRealmCache() {
final String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
this.watcher = osName.startsWith("osx") || osName.startsWith("mac os x")
? new TimestampedRecordValidator()
: new MultiWatcher();
this.watcher = new RecordValidator();
}

public Key createKey(Plugin plugin, ClassLoader parentRealm, Map<String, ClassLoader> foreignImports,
Expand Down

0 comments on commit 67d5b4b

Please sign in to comment.