diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2021-11-17 14:33:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-17 14:33:35 +0100 |
commit | 9954489e6b62916c76f1dacccfaf3d723caee6e9 (patch) | |
tree | ece01b8ca55e5e855e4164f704e8d92ef308bbf0 | |
parent | d56598aac02ed4facb0f0f9b7f982bcf79667299 (diff) | |
parent | d2b39bf7c38a8ec64ae6ad3a18df825392c468b4 (diff) |
Merge pull request #20064 from vespa-engine/hmusum/delete-old-files-belongint-to-sessions-with-unknown-status
Delete files belonging to sessions with unknown status older than a m…
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java | 25 | ||||
-rw-r--r-- | configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java | 23 |
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 { |