Skip to content

Commit

Permalink
GH-1118: update cache once for multiple files being deleted
Browse files Browse the repository at this point in the history
  • Loading branch information
martinlippert committed Oct 13, 2023
1 parent 667a46b commit 6f7f9fd
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2020 Pivotal, Inc.
* Copyright (c) 2019, 2023 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -30,6 +30,7 @@ public interface IndexCache {

void remove(IndexCacheKey cacheKey);
<T extends IndexCacheable> void removeFile(IndexCacheKey symbolCacheKey, String file, Class<T> type);
<T extends IndexCacheable> void removeFiles(IndexCacheKey symbolCacheKey, String[] files, Class<T> type);

default <T extends IndexCacheable> T[] retrieveSymbols(IndexCacheKey cacheKey, String[] files, Class<T> type) {
Pair<T[], Multimap<String, String>> r = retrieve(cacheKey, files, type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,33 @@ public <T extends IndexCacheable> void removeFile(IndexCacheKey cacheKey, String
}
}

@Override
public <T extends IndexCacheable> void removeFiles(IndexCacheKey cacheKey, String[] files, Class<T> type) {
@SuppressWarnings("unchecked")
IndexCacheStore<T> cacheStore = (IndexCacheStore<T>) this.stores.get(cacheKey);

if (cacheStore != null) {

SortedMap<String, Long> timestampedFiles = new TreeMap<>(cacheStore.getTimestampedFiles());
Map<String, Collection<String>> changedDeps = new HashMap<>(cacheStore.getDependencies());
Set<String> docURIs = new HashSet<>();

for (String file : files) {
String docURI = UriUtil.toUri(new File(file)).toASCIIString();
docURIs.add(docURI);

timestampedFiles.remove(file);
changedDeps.remove(file);
}

List<T> cachedSymbols = cacheStore.getSymbols().stream()
.filter(cachedSymbol -> !docURIs.contains(cachedSymbol.getDocURI()))
.collect(Collectors.toList());

save(cacheKey, cachedSymbols, timestampedFiles, changedDeps, type);
}
}

@Override
public void remove(IndexCacheKey cacheKey) {
File cacheStore = new File(cacheDirectory, cacheKey.toString() + ".json");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ public void remove(IndexCacheKey cacheKey) {
public <T extends IndexCacheable> void removeFile(IndexCacheKey symbolCacheKey, String file, Class<T> type) {
}

@Override
public <T extends IndexCacheable> void removeFiles(IndexCacheKey symbolCacheKey, String[] files, Class<T> type) {
}

@Override
public long getModificationTimestamp(IndexCacheKey cacheKey, String docURI) {
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -284,11 +285,16 @@ public void updateFiles(IJavaProject project, DocumentDescriptor[] updatedDocs)

@Override
public void removeFiles(IJavaProject project, String[] docURIs) throws Exception {
String[] files = Arrays.stream(docURIs).map(docURI -> {
try {
return new File(new URI(docURI)).getAbsolutePath();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}).toArray(String[]::new);

IndexCacheKey key = getCacheKey(project);
for (String docUri : docURIs) {
String file = new File(new URI(docUri)).getAbsolutePath();
cache.removeFile(key, file, CachedSymbol.class);
}
cache.removeFiles(key, files, CachedSymbol.class);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,22 @@ public void updateFiles(IJavaProject project, DocumentDescriptor[] updatedDocs)

@Override
public void removeFiles(IJavaProject project, String[] docURIs) throws Exception {

String[] files = Arrays.stream(docURIs).map(docURI -> {
try {
return new File(new URI(docURI)).getAbsolutePath();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}).toArray(String[]::new);

IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
IndexCacheKey diagnosticsCacheKey = getCacheKey(project, DIAGNOSTICS_KEY);

for (String docURI : docURIs) {
String file = new File(new URI(docURI)).getAbsolutePath();

this.cache.removeFile(symbolsCacheKey, file, CachedSymbol.class);
this.cache.removeFile(beansCacheKey, file, CachedBean.class);
this.cache.removeFile(diagnosticsCacheKey, file, CachedDiagnostics.class);
}
this.cache.removeFiles(symbolsCacheKey, files, CachedSymbol.class);
this.cache.removeFiles(beansCacheKey, files, CachedBean.class);
this.cache.removeFiles(diagnosticsCacheKey, files, CachedDiagnostics.class);
}

private DocumentDescriptor[] filterDocuments(IJavaProject project, DocumentDescriptor[] updatedDocs) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
Expand Down Expand Up @@ -212,15 +213,19 @@ public void updateFiles(IJavaProject project, DocumentDescriptor[] updatedDocs)

@Override
public void removeFiles(IJavaProject project, String[] docURIs) throws Exception {
String[] files = Arrays.stream(docURIs).map(docURI -> {
try {
return new File(new URI(docURI)).getAbsolutePath();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}).toArray(String[]::new);

IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);

for (String docURI : docURIs) {
String file = new File(new URI(docURI)).getAbsolutePath();

this.cache.removeFile(symbolsCacheKey, file, CachedSymbol.class);
this.cache.removeFile(beansCacheKey, file, CachedBean.class);
}
this.cache.removeFiles(symbolsCacheKey, files, CachedSymbol.class);
this.cache.removeFiles(beansCacheKey, files, CachedBean.class);
}

private void scanFile(IJavaProject project, String fileName, List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -621,4 +621,82 @@ void testFileDeleted() throws Exception {
assertEquals(ImmutableSet.of(), cachedDependencies.get(file1.toString()));
assertEquals(ImmutableSet.of("dep2"), cachedDependencies.get(file2.toString()));
}

@Test
void testMultipleFilesDeleted() throws Exception {
Path file1 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile1");
Path file2 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile2");
Path file3 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile3");
Path file4 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile4");

Files.createFile(file1);
Files.createFile(file2);
Files.createFile(file3);
Files.createFile(file4);

FileTime timeFile1 = Files.getLastModifiedTime(file1);
FileTime timeFile2 = Files.getLastModifiedTime(file2);
FileTime timeFile3 = Files.getLastModifiedTime(file3);
FileTime timeFile4 = Files.getLastModifiedTime(file4);
String[] files = {
file1.toAbsolutePath().toString(),
file2.toAbsolutePath().toString(),
file3.toAbsolutePath().toString(),
file4.toAbsolutePath().toString()
};

String doc1URI = UriUtil.toUri(file1.toFile()).toASCIIString();
String doc2URI = UriUtil.toUri(file2.toFile()).toASCIIString();
String doc3URI = UriUtil.toUri(file3.toFile()).toASCIIString();
String doc4URI = UriUtil.toUri(file4.toFile()).toASCIIString();

List<CachedSymbol> generatedSymbols = new ArrayList<>();

WorkspaceSymbol symbol1 = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location(doc1URI, new Range(new Position(3, 10), new Position(3, 20)))));
EnhancedSymbolInformation enhancedSymbol1 = new EnhancedSymbolInformation(symbol1, null);

WorkspaceSymbol symbol2 = new WorkspaceSymbol("symbol2", SymbolKind.Field, Either.forLeft(new Location(doc2URI, new Range(new Position(5, 10), new Position(5, 20)))));
EnhancedSymbolInformation enhancedSymbol2 = new EnhancedSymbolInformation(symbol2, null);

WorkspaceSymbol symbol3 = new WorkspaceSymbol("symbol3", SymbolKind.Field, Either.forLeft(new Location(doc3URI, new Range(new Position(20, 11), new Position(20, 30)))));
EnhancedSymbolInformation enhancedSymbol3 = new EnhancedSymbolInformation(symbol3, null);

WorkspaceSymbol symbol4 = new WorkspaceSymbol("symbol4", SymbolKind.Field, Either.forLeft(new Location(doc4URI, new Range(new Position(4, 4), new Position(5, 5)))));
EnhancedSymbolInformation enhancedSymbol4 = new EnhancedSymbolInformation(symbol4, null);

generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1));
generatedSymbols.add(new CachedSymbol(doc2URI, timeFile2.toMillis(), enhancedSymbol2));
generatedSymbols.add(new CachedSymbol(doc3URI, timeFile3.toMillis(), enhancedSymbol3));
generatedSymbols.add(new CachedSymbol(doc4URI, timeFile4.toMillis(), enhancedSymbol4));

Multimap<String, String> dependencies = ImmutableMultimap.of(
file1.toString(), "dep1",
file2.toString(), "dep2"
);
cache.store(CACHE_KEY_VERSION_1, files, generatedSymbols, dependencies, CachedSymbol.class);
// cache.removeFile(CACHE_KEY_VERSION_1, file1.toAbsolutePath().toString(), CachedSymbol.class);
// cache.removeFile(CACHE_KEY_VERSION_1, file3.toAbsolutePath().toString(), CachedSymbol.class);
cache.removeFiles(CACHE_KEY_VERSION_1, new String[] {file1.toAbsolutePath().toString(), file3.toAbsolutePath().toString()}, CachedSymbol.class);

files = new String[]{file2.toAbsolutePath().toString(), file4.toAbsolutePath().toString()};
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(CACHE_KEY_VERSION_1, files, CachedSymbol.class);
CachedSymbol[] cachedSymbols = result.getLeft();
assertNotNull(result);
assertEquals(2, cachedSymbols.length);

assertEquals("symbol2", cachedSymbols[0].getEnhancedSymbol().getSymbol().getName());
assertEquals(SymbolKind.Field, cachedSymbols[0].getEnhancedSymbol().getSymbol().getKind());
assertEquals(new Location(doc2URI, new Range(new Position(5, 10), new Position(5, 20))), cachedSymbols[0].getEnhancedSymbol().getSymbol().getLocation().getLeft());
assertNull(cachedSymbols[0].getEnhancedSymbol().getAdditionalInformation());

assertEquals("symbol4", cachedSymbols[1].getEnhancedSymbol().getSymbol().getName());
assertEquals(SymbolKind.Field, cachedSymbols[1].getEnhancedSymbol().getSymbol().getKind());
assertEquals(new Location(doc4URI, new Range(new Position(4, 4), new Position(5, 5))), cachedSymbols[1].getEnhancedSymbol().getSymbol().getLocation().getLeft());
assertNull(cachedSymbols[1].getEnhancedSymbol().getAdditionalInformation());

Multimap<String, String> cachedDependencies = result.getRight();
assertEquals(ImmutableSet.of(), cachedDependencies.get(file1.toString()));
assertEquals(ImmutableSet.of("dep2"), cachedDependencies.get(file2.toString()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ public void remove(IndexCacheKey cacheKey) {
public <T extends IndexCacheable> void removeFile(IndexCacheKey symbolCacheKey, String file, Class<T> type) {
}

@Override
public <T extends IndexCacheable> void removeFiles(IndexCacheKey symbolCacheKey, String[] files, Class<T> type) {
}

@Override
public long getModificationTimestamp(IndexCacheKey cacheKey, String file) {
Map<String, Long> timestampMap = timestampCache.get(cacheKey);
Expand Down

0 comments on commit 6f7f9fd

Please sign in to comment.