mirror of
https://github.com/apache/maven-mvnd.git
synced 2025-09-24 05:05:10 +00:00
Merge pull request #168 from gnodet/cache-strategy
Use a single cache removal strategy
This commit is contained in:
@@ -22,7 +22,6 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardWatchEventKinds;
|
import java.nio.file.StandardWatchEventKinds;
|
||||||
@@ -30,8 +29,6 @@ import java.nio.file.WatchEvent;
|
|||||||
import java.nio.file.WatchEvent.Kind;
|
import java.nio.file.WatchEvent.Kind;
|
||||||
import java.nio.file.WatchKey;
|
import java.nio.file.WatchKey;
|
||||||
import java.nio.file.WatchService;
|
import java.nio.file.WatchService;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
|
||||||
import java.nio.file.attribute.FileTime;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -40,13 +37,13 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import javax.enterprise.inject.Default;
|
import javax.enterprise.inject.Default;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.apache.maven.RepositoryUtils;
|
import org.apache.maven.RepositoryUtils;
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.eventspy.AbstractEventSpy;
|
import org.apache.maven.eventspy.AbstractEventSpy;
|
||||||
@@ -115,7 +112,7 @@ public class CliPluginRealmCache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.parentRealm = parentRealm;
|
this.parentRealm = parentRealm;
|
||||||
this.foreignImports = (foreignImports != null) ? foreignImports : Collections.<String, ClassLoader> emptyMap();
|
this.foreignImports = (foreignImports != null) ? foreignImports : Collections.emptyMap();
|
||||||
this.filter = dependencyFilter;
|
this.filter = dependencyFilter;
|
||||||
|
|
||||||
int hash = 17;
|
int hash = 17;
|
||||||
@@ -161,19 +158,17 @@ public class CliPluginRealmCache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RecordValidator {
|
static class ValidableCacheRecord extends CacheRecord {
|
||||||
void validateRecords();
|
|
||||||
|
|
||||||
ValidableCacheRecord newRecord(ClassRealm pluginRealm, List<Artifact> pluginArtifacts);
|
private volatile boolean valid = true;
|
||||||
}
|
|
||||||
|
|
||||||
static abstract class ValidableCacheRecord extends CacheRecord {
|
|
||||||
|
|
||||||
public ValidableCacheRecord(ClassRealm realm, List<Artifact> artifacts) {
|
public ValidableCacheRecord(ClassRealm realm, List<Artifact> artifacts) {
|
||||||
super(realm, artifacts);
|
super(realm, artifacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean isValid();
|
public boolean isValid() {
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
ClassRealm realm = getRealm();
|
ClassRealm realm = getRealm();
|
||||||
@@ -185,82 +180,10 @@ public class CliPluginRealmCache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
private final WatchService watchService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -275,7 +198,7 @@ public class CliPluginRealmCache
|
|||||||
*/
|
*/
|
||||||
private final Map<Path, Registration> registrationsByDir = new ConcurrentHashMap<>();
|
private final Map<Path, Registration> registrationsByDir = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public MultiWatcher() {
|
public RecordValidator() {
|
||||||
try {
|
try {
|
||||||
this.watchService = FileSystems.getDefault().newWatchService();
|
this.watchService = FileSystems.getDefault().newWatchService();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -286,7 +209,7 @@ public class CliPluginRealmCache
|
|||||||
/**
|
/**
|
||||||
* Watch the JARs associated with the given {@code record} for deletions and modifications.
|
* 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) {
|
void add(ValidableCacheRecord record) {
|
||||||
record.getArtifacts().stream()
|
record.getArtifacts().stream()
|
||||||
@@ -323,7 +246,7 @@ public class CliPluginRealmCache
|
|||||||
/**
|
/**
|
||||||
* Stopn watching the JARs associated with the given {@code record} for deletions and modifications.
|
* 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) {
|
void remove(ValidableCacheRecord record) {
|
||||||
record.getArtifacts().stream()
|
record.getArtifacts().stream()
|
||||||
@@ -368,7 +291,7 @@ public class CliPluginRealmCache
|
|||||||
synchronized (records) {
|
synchronized (records) {
|
||||||
for (ValidableCacheRecord record : records) {
|
for (ValidableCacheRecord record : records) {
|
||||||
log.debug("Invalidating recorder of path {}", path);
|
log.debug("Invalidating recorder of path {}", path);
|
||||||
((WatchedCacheRecord) record).valid = false;
|
record.valid = false;
|
||||||
remove(record);
|
remove(record);
|
||||||
}
|
}
|
||||||
records.clear();
|
records.clear();
|
||||||
@@ -383,7 +306,7 @@ public class CliPluginRealmCache
|
|||||||
if (records != null) {
|
if (records != null) {
|
||||||
synchronized (records) {
|
synchronized (records) {
|
||||||
for (ValidableCacheRecord record : records) {
|
for (ValidableCacheRecord record : records) {
|
||||||
((WatchedCacheRecord) record).valid = false;
|
record.valid = false;
|
||||||
remove(record);
|
remove(record);
|
||||||
}
|
}
|
||||||
records.clear();
|
records.clear();
|
||||||
@@ -409,29 +332,14 @@ public class CliPluginRealmCache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValidableCacheRecord newRecord(ClassRealm pluginRealm, List<Artifact> pluginArtifacts) {
|
public ValidableCacheRecord newRecord(ClassRealm pluginRealm, List<Artifact> pluginArtifacts) {
|
||||||
final ValidableCacheRecord result = new WatchedCacheRecord(pluginRealm, pluginArtifacts);
|
final ValidableCacheRecord result = new ValidableCacheRecord(pluginRealm, pluginArtifacts);
|
||||||
add(result);
|
add(result);
|
||||||
return 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);
|
private static final Logger log = LoggerFactory.getLogger(CliPluginRealmCache.class);
|
||||||
protected final Map<Key, ValidableCacheRecord> cache = new ConcurrentHashMap<>();
|
protected final Map<Key, ValidableCacheRecord> cache = new ConcurrentHashMap<>();
|
||||||
private final RecordValidator watcher;
|
private final RecordValidator watcher;
|
||||||
@@ -446,6 +354,7 @@ public class CliPluginRealmCache
|
|||||||
/* Store the multiModuleProjectDirectory path */
|
/* Store the multiModuleProjectDirectory path */
|
||||||
multiModuleProjectDirectory = ((MavenExecutionRequest) event).getMultiModuleProjectDirectory().toPath();
|
multiModuleProjectDirectory = ((MavenExecutionRequest) event).getMultiModuleProjectDirectory().toPath();
|
||||||
} else if (event instanceof MavenExecutionResult) {
|
} else if (event instanceof MavenExecutionResult) {
|
||||||
|
String rootUri = multiModuleProjectDirectory.toUri().toString();
|
||||||
/* Evict the entries refering to jars under multiModuleProjectDirectory */
|
/* Evict the entries refering to jars under multiModuleProjectDirectory */
|
||||||
final Iterator<Entry<Key, ValidableCacheRecord>> i = cache.entrySet().iterator();
|
final Iterator<Entry<Key, ValidableCacheRecord>> i = cache.entrySet().iterator();
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
@@ -474,9 +383,7 @@ public class CliPluginRealmCache
|
|||||||
|
|
||||||
public CliPluginRealmCache() {
|
public CliPluginRealmCache() {
|
||||||
final String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
|
final String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
|
||||||
this.watcher = osName.startsWith("osx") || osName.startsWith("mac os x")
|
this.watcher = new RecordValidator();
|
||||||
? new TimestampedRecordValidator()
|
|
||||||
: new MultiWatcher();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Key createKey(Plugin plugin, ClassLoader parentRealm, Map<String, ClassLoader> foreignImports,
|
public Key createKey(Plugin plugin, ClassLoader parentRealm, Map<String, ClassLoader> foreignImports,
|
||||||
|
Reference in New Issue
Block a user