summaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
authorHarald Musum <musum@yahooinc.com>2021-11-17 14:04:54 +0100
committerHarald Musum <musum@yahooinc.com>2021-11-17 14:04:54 +0100
commitd2b39bf7c38a8ec64ae6ad3a18df825392c468b4 (patch)
treefe3f276e664b6d1de043ae3dc1afafc0bb1ff3ea /configserver
parent6ee5b6bf5acbabc505f8d81072b3a96d5969025e (diff)
Delete files belonging to sessions with unknown status older than a month
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java25
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java23
2 files changed, 44 insertions, 4 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java
index 0aeea5ce2d5..95be59e4d26 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java
@@ -53,8 +53,10 @@ import org.apache.zookeeper.KeeperException;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
@@ -80,6 +82,7 @@ import java.util.logging.Logger;
import java.util.stream.Collectors;
import static com.yahoo.vespa.curator.Curator.CompletionWaiter;
+import static java.nio.file.Files.readAttributes;
/**
*
@@ -593,9 +596,27 @@ public class SessionRepository {
return candidate.getCreateTime().plus(sessionLifetime).isBefore(clock.instant());
}
- // Sessions with state other than UNKNOWN or ACTIVATE
+ // Sessions with state other than UNKNOWN or ACTIVATE or old sessions in UNKNOWN state
private boolean canBeDeleted(LocalSession candidate) {
- return ! List.of(Session.Status.UNKNOWN, Session.Status.ACTIVATE).contains(candidate.getStatus());
+ return ! List.of(Session.Status.UNKNOWN, Session.Status.ACTIVATE).contains(candidate.getStatus())
+ || oldSessionDirWithNonExistingSession(candidate);
+ }
+
+ private boolean oldSessionDirWithNonExistingSession(LocalSession session) {
+ File sessionDir = tenantFileSystemDirs.getUserApplicationDir(session.getSessionId());
+ return sessionDir.exists()
+ && session.getStatus() == Session.Status.UNKNOWN
+ && created(sessionDir).plus(Duration.ofDays(30)).isBefore(clock.instant());
+ }
+
+ private Instant created(File file) {
+ BasicFileAttributes fileAttributes;
+ try {
+ fileAttributes = readAttributes(file.toPath(), BasicFileAttributes.class);
+ return fileAttributes.creationTime().toInstant();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
}
private void ensureSessionPathDoesNotExist(long sessionId) {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java
index ce926016bd4..63c569fb17a 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java
@@ -58,7 +58,10 @@ import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.nio.file.Files;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.FileTime;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
@@ -462,10 +465,10 @@ public class ApplicationRepositoryTest {
assertEquals(1, sessionRepository.getLocalSessions().size());
// Create a local session without any data in zookeeper (corner case seen in production occasionally)
- // and check that expiring local sessions still work
+ // and check that expiring local sessions still works
int sessionId = 6;
TenantName tenantName = tester.tenant().getName();
- Files.createDirectory(new TenantFileSystemDirs(serverdb, tenantName).getUserApplicationDir(sessionId).toPath());
+ java.nio.file.Path dir = Files.createDirectory(new TenantFileSystemDirs(serverdb, tenantName).getUserApplicationDir(sessionId).toPath());
LocalSession localSession2 = new LocalSession(tenant1,
sessionId,
FilesApplicationPackage.fromFile(testApp),
@@ -490,6 +493,12 @@ public class ApplicationRepositoryTest {
// Check that trying to expire when there are no active sessions works
tester.applicationRepository().deleteExpiredLocalSessions();
+ assertEquals(2, sessionRepository.getLocalSessions().size());
+
+ // Set older created timestamp for session dir for local session without any data in zookeeper, should be deleted
+ setCreatedTime(dir, Instant.now().minus(Duration.ofDays(31)));
+ tester.applicationRepository().deleteExpiredLocalSessions();
+ assertEquals(1, sessionRepository.getLocalSessions().size());
}
@Test
@@ -740,6 +749,16 @@ public class ApplicationRepositoryTest {
return applicationRepository.getMetadataFromLocalSession(tenant, sessionId);
}
+ private void setCreatedTime(java.nio.file.Path file, Instant createdTime) {
+ try {
+ BasicFileAttributeView attributes = Files.getFileAttributeView(file, BasicFileAttributeView.class);
+ FileTime time = FileTime.fromMillis(createdTime.toEpochMilli());
+ attributes.setTimes(time, time, time);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
/** Stores all added or set values for each metric and context. */
static class MockMetric implements Metric {