diff options
Diffstat (limited to 'configserver/src/main/java')
10 files changed, 131 insertions, 285 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java index 157e1bd838c..b454e5b063d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java @@ -50,9 +50,7 @@ import com.yahoo.vespa.config.server.http.v2.ProtonMetricsResponse; import com.yahoo.vespa.config.server.metrics.DeploymentMetricsRetriever; import com.yahoo.vespa.config.server.metrics.ProtonMetricsRetriever; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; -import com.yahoo.vespa.config.server.session.LocalSession; import com.yahoo.vespa.config.server.session.PrepareParams; -import com.yahoo.vespa.config.server.session.RemoteSession; import com.yahoo.vespa.config.server.session.Session; import com.yahoo.vespa.config.server.session.SessionRepository; import com.yahoo.vespa.config.server.session.SilentDeployLogger; @@ -482,10 +480,10 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye Optional<Long> activeSession = tenantApplications.activeSessionOf(applicationId); if (activeSession.isEmpty()) return false; - // Deleting an application is done by deleting the remote session, other config + // Deleting an application is done by deleting the session, other config // servers will pick this up and clean up through the watcher in this class try { - Session session = getRemoteSession(tenant, activeSession.get()); + Session session = getSession(tenant, activeSession.get()); tenant.getSessionRepository().delete(session); } catch (NotFoundException e) { log.log(Level.INFO, TenantRepository.logPre(applicationId) + "Active session exists, but has not been deleted properly. Trying to cleanup"); @@ -609,7 +607,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye Tenant tenant = getTenant(applicationId); if (tenant == null) throw new NotFoundException("Tenant '" + applicationId.tenant() + "' not found"); long sessionId = getSessionIdForApplication(tenant, applicationId); - RemoteSession session = getRemoteSession(tenant, sessionId); + Session session = getSession(tenant, sessionId); SessionRepository sessionRepository = tenant.getSessionRepository(); return sessionRepository.ensureApplicationLoaded(session).getForVersionOrLatest(version, clock.instant()); } catch (NotFoundException e) { @@ -761,7 +759,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye * * @return the active session, or null if there is no active session for the given application id. */ - public RemoteSession getActiveRemoteSession(ApplicationId applicationId) { + public Session getActiveRemoteSession(ApplicationId applicationId) { Tenant tenant = getTenant(applicationId); if (tenant == null) throw new IllegalArgumentException("Could not find any tenant for '" + applicationId + "'"); return getActiveSession(tenant, applicationId); @@ -781,14 +779,14 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye } public void validateThatSessionIsNotActive(Tenant tenant, long sessionId) { - Session session = getRemoteSession(tenant, sessionId); + Session session = getSession(tenant, sessionId); if (Session.Status.ACTIVATE.equals(session.getStatus())) { throw new IllegalStateException("Session is active: " + sessionId); } } public void validateThatSessionIsPrepared(Tenant tenant, long sessionId) { - Session session = getRemoteSession(tenant, sessionId); + Session session = getSession(tenant, sessionId); if ( ! Session.Status.PREPARE.equals(session.getStatus())) throw new IllegalStateException("Session not prepared: " + sessionId); } @@ -819,9 +817,9 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye return session.getSessionId(); } - public void deleteExpiredLocalSessions() { - Map<Tenant, Collection<LocalSession>> sessionsPerTenant = new HashMap<>(); - tenantRepository.getAllTenants().forEach(tenant -> sessionsPerTenant.put(tenant, tenant.getSessionRepository().getLocalSessions())); + public void deleteExpiredSessions() { + Map<Tenant, Collection<Session>> sessionsPerTenant = new HashMap<>(); + tenantRepository.getAllTenants().forEach(tenant -> sessionsPerTenant.put(tenant, tenant.getSessionRepository().getSessions())); Set<ApplicationId> applicationIds = new HashSet<>(); sessionsPerTenant.values() @@ -839,18 +837,6 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye sessionsPerTenant.keySet().forEach(tenant -> tenant.getSessionRepository().deleteExpiredSessions(activeSessions)); } - public int deleteExpiredRemoteSessions(Duration expiryTime) { - return deleteExpiredRemoteSessions(clock, expiryTime); - } - - public int deleteExpiredRemoteSessions(Clock clock, Duration expiryTime) { - return tenantRepository.getAllTenants() - .stream() - .map(tenant -> tenant.getSessionRepository().deleteExpiredRemoteSessions(clock, expiryTime)) - .mapToInt(i -> i) - .sum(); - } - // ---------------- Tenant operations ---------------------------------------------------------------- @@ -923,14 +909,14 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye } private Session getLocalSession(Tenant tenant, long sessionId) { - Session session = tenant.getSessionRepository().getLocalSession(sessionId); + Session session = tenant.getSessionRepository().getSession(sessionId); if (session == null) throw new NotFoundException("Session " + sessionId + " was not found"); return session; } - private RemoteSession getRemoteSession(Tenant tenant, long sessionId) { - RemoteSession session = tenant.getSessionRepository().getRemoteSession(sessionId); + private Session getSession(Tenant tenant, long sessionId) { + Session session = tenant.getSessionRepository().getSession(sessionId); if (session == null) throw new NotFoundException("Session " + sessionId + " was not found"); return session; @@ -966,13 +952,13 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye // TODO: Merge this and getActiveSession(), they are almost identical private Session getExistingSession(Tenant tenant, ApplicationId applicationId) { TenantApplications applicationRepo = tenant.getApplicationRepo(); - return getRemoteSession(tenant, applicationRepo.requireActiveSessionOf(applicationId)); + return getSession(tenant, applicationRepo.requireActiveSessionOf(applicationId)); } - public RemoteSession getActiveSession(Tenant tenant, ApplicationId applicationId) { + public Session getActiveSession(Tenant tenant, ApplicationId applicationId) { TenantApplications applicationRepo = tenant.getApplicationRepo(); if (applicationRepo.activeApplications().contains(applicationId)) { - return tenant.getSessionRepository().getRemoteSession(applicationRepo.requireActiveSessionOf(applicationId)); + return tenant.getSessionRepository().getSession(applicationRepo.requireActiveSessionOf(applicationId)); } return null; } @@ -980,7 +966,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye public Session getActiveLocalSession(Tenant tenant, ApplicationId applicationId) { TenantApplications applicationRepo = tenant.getApplicationRepo(); if (applicationRepo.activeApplications().contains(applicationId)) { - return tenant.getSessionRepository().getLocalSession(applicationRepo.requireActiveSessionOf(applicationId)); + return tenant.getSessionRepository().getSession(applicationRepo.requireActiveSessionOf(applicationId)); } return null; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java index 7d58682947f..3c22c05ae2d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java @@ -94,7 +94,7 @@ public class Deployment implements com.yahoo.config.provision.Deployment { PrepareParams params = this.params.get(); ApplicationId applicationId = params.getApplicationId(); try (ActionTimer timer = applicationRepository.timerFor(applicationId, "deployment.prepareMillis")) { - this.configChangeActions = tenant.getSessionRepository().prepareLocalSession(session, deployLogger, params, clock.instant()); + this.configChangeActions = tenant.getSessionRepository().prepareSession(session, deployLogger, params, clock.instant()); this.prepared = true; } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java index aa709b3bf37..f73afc7c711 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java @@ -70,7 +70,7 @@ public class ApplicationPackageMaintainer extends ConfigServerMaintainer { continue; } } - createLocalSessionIfMissing(applicationId, sessionId); + createSessionIfMissing(applicationId, sessionId); } } } @@ -83,11 +83,11 @@ public class ApplicationPackageMaintainer extends ConfigServerMaintainer { super.close(); } - private void createLocalSessionIfMissing(ApplicationId applicationId, long sessionId) { + private void createSessionIfMissing(ApplicationId applicationId, long sessionId) { Tenant tenant = applicationRepository.getTenant(applicationId); SessionRepository sessionRepository = tenant.getSessionRepository(); - if (sessionRepository.getLocalSession(sessionId) == null) - sessionRepository.createLocalSessionFromDistributedApplicationPackage(sessionId); + if (sessionRepository.getSession(sessionId) == null) + sessionRepository.createSessionFromDistributedApplicationPackage(sessionId); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/SessionsMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/SessionsMaintainer.java index 19534bba810..32b067b5731 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/SessionsMaintainer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/SessionsMaintainer.java @@ -1,7 +1,6 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.maintenance; -import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.flags.FlagSource; @@ -16,23 +15,14 @@ import java.time.Duration; * @author hmusum */ public class SessionsMaintainer extends ConfigServerMaintainer { - private final boolean hostedVespa; SessionsMaintainer(ApplicationRepository applicationRepository, Curator curator, Duration interval, FlagSource flagSource) { super(applicationRepository, curator, flagSource, Duration.ofMinutes(1), interval); - this.hostedVespa = applicationRepository.configserverConfig().hostedVespa(); } @Override protected boolean maintain() { - applicationRepository.deleteExpiredLocalSessions(); - - if (hostedVespa) { - Duration expiryTime = Duration.ofMinutes(90); - int deleted = applicationRepository.deleteExpiredRemoteSessions(expiryTime); - log.log(LogLevel.FINE, () -> "Deleted " + deleted + " expired remote sessions older than " + expiryTime); - } - + applicationRepository.deleteExpiredSessions(); return true; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java deleted file mode 100644 index f842578b657..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.session; - -import com.yahoo.config.application.api.ApplicationPackage; -import com.yahoo.config.provision.TenantName; - -/** - * A LocalSession is a session that has been created locally on this configserver. A local session can be edited and - * prepared. Deleting a local session will ensure that the local filesystem state and global zookeeper state is - * cleaned for this session. - * - * @author Ulf Lilleengen - */ -// This is really the store of an application, whether it is active or in an edit session -// TODO: Separate the "application store" and "session" aspects - the latter belongs in the HTTP layer -bratseth -public class LocalSession extends Session { - - /** - * Creates a session. This involves loading the application, validating it and distributing it. - * - * @param sessionId The session id for this session. - */ - public LocalSession(TenantName tenant, long sessionId, ApplicationPackage applicationPackage, - SessionZooKeeperClient sessionZooKeeperClient) { - super(tenant, sessionId, sessionZooKeeperClient, applicationPackage); - } - -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java deleted file mode 100644 index de5f1392242..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.session; - -import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.config.server.application.ApplicationSet; - -import java.util.Objects; -import java.util.Optional; - -/** - * A RemoteSession represents a session created on another config server. This session can - * be regarded as read only, and this interface only allows reading information about a session. - * - * @author Ulf Lilleengen - */ -public class RemoteSession extends Session { - - private final Optional<ApplicationSet> applicationSet; - - /** - * Creates a session. This involves loading the application, validating it and distributing it. - * - * @param tenant The name of the tenant creating session - * @param sessionId The session id for this session. - * @param zooKeeperClient a SessionZooKeeperClient instance - */ - RemoteSession(TenantName tenant, long sessionId, SessionZooKeeperClient zooKeeperClient) { - this(tenant, sessionId, zooKeeperClient, Optional.empty()); - } - - /** - * Creates a remote session, with application set - * - * @param tenant The name of the tenant creating session - * @param sessionId The session id for this session. - * @param zooKeeperClient a SessionZooKeeperClient instance - * @param applicationSet current application set for this session - */ - RemoteSession(TenantName tenant, long sessionId, SessionZooKeeperClient zooKeeperClient, Optional<ApplicationSet> applicationSet) { - super(tenant, sessionId, zooKeeperClient); - this.applicationSet = applicationSet; - } - - @Override - Optional<ApplicationSet> applicationSet() { return applicationSet; } - - public synchronized RemoteSession activated(ApplicationSet applicationSet) { - Objects.requireNonNull(applicationSet, "applicationSet cannot be null"); - return new RemoteSession(tenant, sessionId, sessionZooKeeperClient, Optional.of(applicationSet)); - } - - public synchronized RemoteSession deactivated() { - return new RemoteSession(tenant, sessionId, sessionZooKeeperClient, Optional.empty()); - } - - @Override - public String toString() { - return super.toString() + ",application set=" + applicationSet; - } - -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java index 69dfc4d627d..d5e158cd9ac 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java @@ -17,38 +17,34 @@ import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.tenant.TenantRepository; import java.time.Instant; +import java.util.Objects; import java.util.Optional; /** - * A session represents an instance of an application that can be edited, prepared and activated. This - * class represents the common stuff between sessions working on the local file - * system ({@link LocalSession}s) and sessions working on zookeeper ({@link RemoteSession}s). + * A session represents an instance of an application that can be edited, prepared and activated. * * @author Ulf Lilleengen * @author hmusum */ -public abstract class Session implements Comparable<Session> { +public class Session implements Comparable<Session> { protected final long sessionId; protected final TenantName tenant; protected final SessionZooKeeperClient sessionZooKeeperClient; protected final Optional<ApplicationPackage> applicationPackage; + private final Optional<ApplicationSet> applicationSet; - protected Session(TenantName tenant, long sessionId, SessionZooKeeperClient sessionZooKeeperClient) { - this(tenant, sessionId, sessionZooKeeperClient, Optional.empty()); + public Session(TenantName tenant, long sessionId, SessionZooKeeperClient sessionZooKeeperClient, ApplicationPackage applicationPackage) { + this(tenant, sessionId, sessionZooKeeperClient, Optional.of(applicationPackage), Optional.empty()); } - protected Session(TenantName tenant, long sessionId, SessionZooKeeperClient sessionZooKeeperClient, - ApplicationPackage applicationPackage) { - this(tenant, sessionId, sessionZooKeeperClient, Optional.of(applicationPackage)); - } - - private Session(TenantName tenant, long sessionId, SessionZooKeeperClient sessionZooKeeperClient, - Optional<ApplicationPackage> applicationPackage) { + public Session(TenantName tenant, long sessionId, SessionZooKeeperClient sessionZooKeeperClient, + Optional<ApplicationPackage> applicationPackage, Optional<ApplicationSet> applicationSet) { this.tenant = tenant; this.sessionId = sessionId; this.sessionZooKeeperClient = sessionZooKeeperClient; this.applicationPackage = applicationPackage; + this.applicationSet = applicationSet; } public final long getSessionId() { @@ -63,9 +59,18 @@ public abstract class Session implements Comparable<Session> { return sessionZooKeeperClient; } + public synchronized Session activated(ApplicationSet applicationSet) { + Objects.requireNonNull(applicationSet, "applicationSet cannot be null"); + return new Session(tenant, sessionId, sessionZooKeeperClient, applicationPackage, Optional.of(applicationSet)); + } + + public synchronized Session deactivated() { + return new Session(tenant, sessionId, sessionZooKeeperClient, applicationPackage, Optional.empty()); + } + @Override public String toString() { - return "Session,id=" + sessionId; + return "Session,id=" + sessionId + ",application set=" + applicationSet + ",application package=" + applicationPackage; } public long getActiveSessionAtCreate() { @@ -181,14 +186,14 @@ public abstract class Session implements Comparable<Session> { return applicationPackage.orElseThrow(() -> new RuntimeException("No application package found for " + this)); } - public ApplicationFile getApplicationFile(Path relativePath, LocalSession.Mode mode) { + public ApplicationFile getApplicationFile(Path relativePath, Session.Mode mode) { if (mode.equals(Session.Mode.WRITE)) { markSessionEdited(); } return getApplicationPackage().getFile(relativePath); } - Optional<ApplicationSet> applicationSet() { return Optional.empty(); }; + Optional<ApplicationSet> applicationSet() { return applicationSet; } private void markSessionEdited() { setStatus(Session.Status.NEW); 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 59146c339d3..7d92cc88783 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 @@ -73,8 +73,7 @@ public class SessionRepository { private static final FilenameFilter sessionApplicationsFilter = (dir, name) -> name.matches("\\d+"); private static final long nonExistingActiveSessionId = 0; - private final Map<Long, LocalSession> localSessionCache = new ConcurrentHashMap<>(); - private final Map<Long, RemoteSession> remoteSessionCache = new ConcurrentHashMap<>(); + private final Map<Long, Session> sessionCache = new ConcurrentHashMap<>(); private final Map<Long, SessionStateWatcher> sessionStateWatchers = new HashMap<>(); private final Duration sessionLifetime; private final Clock clock; @@ -104,36 +103,27 @@ public class SessionRepository { this.applicationRepo = applicationRepo; this.sessionPreparer = sessionPreparer; this.metrics = componentRegistry.getMetrics().getOrCreateMetricUpdater(Metrics.createDimensions(tenantName)); - loadSessions(); // Needs to be done before creating cache below + loadAll(); // Needs to be done before creating cache below this.directoryCache = curator.createDirectoryCache(sessionsPath.getAbsolute(), false, false, componentRegistry.getZkCacheExecutor()); this.directoryCache.addListener(this::childEvent); this.directoryCache.start(); } - private void loadSessions() { - loadLocalSessions(); - loadRemoteSessions(); + private void loadAll() { + loadSessionsFromFileSystem(); + loadSessions(); } - // ---------------- Local sessions ---------------------------------------------------------------- - - public synchronized void addLocalSession(LocalSession session) { + public synchronized void addSession(Session session) { long sessionId = session.getSessionId(); - localSessionCache.put(sessionId, session); - if (remoteSessionCache.get(sessionId) == null) { - createRemoteSession(sessionId); - } - } - - public LocalSession getLocalSession(long sessionId) { - return localSessionCache.get(sessionId); + sessionCache.put(sessionId, session); } - public Collection<LocalSession> getLocalSessions() { - return localSessionCache.values(); + public Collection<Session> getSessions() { + return sessionCache.values(); } - private void loadLocalSessions() { + private void loadSessionsFromFileSystem() { File[] sessions = tenantFileSystemDirs.sessionsPath().listFiles(sessionApplicationsFilter); if (sessions == null) return; @@ -147,7 +137,7 @@ public class SessionRepository { } } - public ConfigChangeActions prepareLocalSession(Session session, DeployLogger logger, PrepareParams params, Instant now) { + public ConfigChangeActions prepareSession(Session session, DeployLogger logger, PrepareParams params, Instant now) { applicationRepo.createApplication(params.getApplicationId()); // TODO jvenstad: This is wrong, but it has to be done now, since preparation can change the application ID of a session :( logger.log(Level.FINE, "Created application " + params.getApplicationId()); long sessionId = session.getSessionId(); @@ -171,10 +161,10 @@ public class SessionRepository { * @param timeoutBudget timeout for creating session and waiting for other servers. * @return a new session */ - public LocalSession createSessionFromExisting(Session existingSession, boolean internalRedeploy, TimeoutBudget timeoutBudget) { + public Session createSessionFromExisting(Session existingSession, boolean internalRedeploy, TimeoutBudget timeoutBudget) { ApplicationId existingApplicationId = existingSession.getApplicationId(); File existingApp = getSessionAppDir(existingSession.getSessionId()); - LocalSession session = createSessionFromApplication(existingApp, existingApplicationId, internalRedeploy, timeoutBudget); + Session session = createSessionFromApplication(existingApp, existingApplicationId, internalRedeploy, timeoutBudget); // Note: Setters below need to be kept in sync with calls in SessionPreparer.writeStateToZooKeeper() session.setApplicationId(existingApplicationId); session.setApplicationPackageReference(existingSession.getApplicationPackageReference()); @@ -192,93 +182,59 @@ public class SessionRepository { * @param timeoutBudget Timeout for creating session and waiting for other servers. * @return a new session */ - public LocalSession createSessionFromApplicationPackage(File applicationDirectory, ApplicationId applicationId, TimeoutBudget timeoutBudget) { + public Session createSessionFromApplicationPackage(File applicationDirectory, ApplicationId applicationId, TimeoutBudget timeoutBudget) { applicationRepo.createApplication(applicationId); return createSessionFromApplication(applicationDirectory, applicationId, false, timeoutBudget); } - /** - * This method is used when creating a session based on a remote session and the distributed application package - * It does not wait for session being created on other servers - */ - private void createLocalSession(File applicationFile, ApplicationId applicationId, long sessionId) { - try { - ApplicationPackage applicationPackage = createApplicationPackage(applicationFile, applicationId, sessionId, false); - createLocalSession(sessionId, applicationPackage); - } catch (Exception e) { - throw new RuntimeException("Error creating session " + sessionId, e); - } - } - // Will delete session data in ZooKeeper and file system - public void deleteLocalSession(LocalSession session) { + public void deleteLocalSession(Session session) { long sessionId = session.getSessionId(); - log.log(Level.FINE, () -> "Deleting local session " + sessionId); + log.log(Level.FINE, () -> "Deleting session " + sessionId); SessionStateWatcher watcher = sessionStateWatchers.remove(sessionId); if (watcher != null) watcher.close(); - localSessionCache.remove(sessionId); + sessionCache.remove(sessionId); NestedTransaction transaction = new NestedTransaction(); transaction.add(FileTransaction.from(FileOperations.delete(getSessionAppDir(sessionId).getAbsolutePath()))); transaction.commit(); } private void deleteAllSessions() { - List<LocalSession> sessions = new ArrayList<>(localSessionCache.values()); - for (LocalSession session : sessions) { + List<Session> sessions = new ArrayList<>(sessionCache.values()); + for (Session session : sessions) { deleteLocalSession(session); } } - // ---------------- Remote sessions ---------------------------------------------------------------- - - public RemoteSession getRemoteSession(long sessionId) { - return remoteSessionCache.get(sessionId); + public Session getSession(long sessionId) { + return sessionCache.get(sessionId); } public List<Long> getRemoteSessionsFromZooKeeper() { return getSessionList(curator.getChildren(sessionsPath)); } - public synchronized RemoteSession createRemoteSession(long sessionId) { + public synchronized Session createSession(long sessionId) { SessionZooKeeperClient sessionZKClient = createSessionZooKeeperClient(sessionId); - RemoteSession session = new RemoteSession(tenantName, sessionId, sessionZKClient); - remoteSessionCache.put(sessionId, session); + Session session = new Session(tenantName, sessionId, sessionZKClient, Optional.empty(), Optional.empty()); + sessionCache.put(sessionId, session); loadSessionIfActive(session); updateSessionStateWatcher(sessionId, session); return session; } - public int deleteExpiredRemoteSessions(Clock clock, Duration expiryTime) { - int deleted = 0; - for (long sessionId : getRemoteSessionsFromZooKeeper()) { - Session session = remoteSessionCache.get(sessionId); - if (session == null) continue; // Internal sessions not in sync with zk, continue - if (session.getStatus() == Session.Status.ACTIVATE) continue; - if (sessionHasExpired(session.getCreateTime(), expiryTime, clock)) { - log.log(Level.FINE, () -> "Remote session " + sessionId + " for " + tenantName + " has expired, deleting it"); - deleteRemoteSessionFromZooKeeper(session); - deleted++; - } - } - return deleted; - } - - public void deactivateAndUpdateCache(RemoteSession remoteSession) { - RemoteSession session = remoteSession.deactivated(); - remoteSessionCache.put(session.getSessionId(), session); + public void deactivateAndUpdateCache(Session session) { + Session deactivated = session.deactivated(); + sessionCache.put(deactivated.getSessionId(), deactivated); } - public void deleteRemoteSessionFromZooKeeper(Session session) { + public void deleteSessionFromZooKeeper(Session session) { SessionZooKeeperClient sessionZooKeeperClient = createSessionZooKeeperClient(session.getSessionId()); Transaction transaction = sessionZooKeeperClient.deleteTransaction(); transaction.commit(); transaction.close(); } - private boolean sessionHasExpired(Instant created, Duration expiryTime, Clock clock) { - return (created.plus(expiryTime).isBefore(clock.instant())); - } - private List<Long> getSessionListFromDirectoryCache(List<ChildData> children) { return getSessionList(children.stream() .map(child -> Path.fromString(child.getPath()).getName()) @@ -289,7 +245,7 @@ public class SessionRepository { return children.stream().map(Long::parseLong).collect(Collectors.toList()); } - private void loadRemoteSessions() throws NumberFormatException { + private void loadSessions() throws NumberFormatException { getRemoteSessionsFromZooKeeper().forEach(this::sessionAdded); } @@ -299,16 +255,16 @@ public class SessionRepository { * @param sessionId session id for the new session */ public synchronized void sessionAdded(long sessionId) { - log.log(Level.FINE, () -> "Adding remote session " + sessionId); - Session session = createRemoteSession(sessionId); + log.log(Level.FINE, () -> "Adding session " + sessionId); + Session session = createSession(sessionId); if (session.getStatus() == Session.Status.NEW) { log.log(Level.FINE, () -> session.logPre() + "Confirming upload for session " + sessionId); confirmUpload(session); } - createLocalSessionFromDistributedApplicationPackage(sessionId); + createSessionFromDistributedApplicationPackage(sessionId); } - void activate(RemoteSession session) { + void activate(Session session) { long sessionId = session.getSessionId(); Curator.CompletionWaiter waiter = createSessionZooKeeperClient(sessionId).getActiveWaiter(); log.log(Level.FINE, () -> session.logPre() + "Getting session from repo: " + session); @@ -320,28 +276,21 @@ public class SessionRepository { log.log(Level.INFO, session.logPre() + "Session activated: " + sessionId); } - public void delete(Session remoteSession) { - long sessionId = remoteSession.getSessionId(); - // TODO: Change log level to FINE when debugging is finished - log.log(Level.INFO, () -> remoteSession.logPre() + "Deactivating and deleting remote session " + sessionId); - deleteRemoteSessionFromZooKeeper(remoteSession); - remoteSessionCache.remove(sessionId); - LocalSession localSession = getLocalSession(sessionId); - if (localSession != null) { - // TODO: Change log level to FINE when debugging is finished - log.log(Level.INFO, () -> localSession.logPre() + "Deleting local session " + sessionId); - deleteLocalSession(localSession); - } + public void delete(Session session) { + long sessionId = session.getSessionId(); + deleteSessionFromZooKeeper(session); + sessionCache.remove(sessionId); + deleteLocalSession(session); } private void sessionRemoved(long sessionId) { SessionStateWatcher watcher = sessionStateWatchers.remove(sessionId); if (watcher != null) watcher.close(); - remoteSessionCache.remove(sessionId); + sessionCache.remove(sessionId); metrics.incRemovedSessions(); } - private void loadSessionIfActive(RemoteSession session) { + private void loadSessionIfActive(Session session) { for (ApplicationId applicationId : applicationRepo.activeApplications()) { if (applicationRepo.requireActiveSessionOf(applicationId) == session.getSessionId()) { log.log(Level.FINE, () -> "Found active application for session " + session.getSessionId() + " , loading it"); @@ -352,22 +301,22 @@ public class SessionRepository { } } - void prepareRemoteSession(RemoteSession session) { + void prepare(Session session) { SessionZooKeeperClient sessionZooKeeperClient = createSessionZooKeeperClient(session.getSessionId()); Curator.CompletionWaiter waiter = sessionZooKeeperClient.getPrepareWaiter(); ensureApplicationLoaded(session); notifyCompletion(waiter, session); } - public ApplicationSet ensureApplicationLoaded(RemoteSession session) { + public ApplicationSet ensureApplicationLoaded(Session session) { if (session.applicationSet().isPresent()) { return session.applicationSet().get(); } ApplicationSet applicationSet = loadApplication(session); - RemoteSession activated = session.activated(applicationSet); + Session activated = session.activated(applicationSet); long sessionId = activated.getSessionId(); - remoteSessionCache.put(sessionId, activated); + sessionCache.put(sessionId, activated); updateSessionStateWatcher(sessionId, activated); return applicationSet; @@ -427,7 +376,7 @@ public class SessionRepository { private void nodeChanged() { zkWatcherExecutor.execute(() -> { Multiset<Session.Status> sessionMetrics = HashMultiset.create(); - for (Session session : remoteSessionCache.values()) { + for (Session session : sessionCache.values()) { sessionMetrics.add(session.getStatus()); } metrics.setNewSessions(sessionMetrics.count(Session.Status.NEW)); @@ -458,20 +407,20 @@ public class SessionRepository { public void deleteExpiredSessions(Map<ApplicationId, Long> activeSessions) { log.log(Level.FINE, () -> "Purging old sessions for tenant '" + tenantName + "'"); try { - for (LocalSession candidate : localSessionCache.values()) { + for (Session candidate : sessionCache.values()) { Instant createTime = candidate.getCreateTime(); log.log(Level.FINE, () -> "Candidate session for deletion: " + candidate.getSessionId() + ", created: " + createTime); // Sessions with state other than ACTIVATE if (hasExpired(candidate) && !isActiveSession(candidate)) { - deleteLocalSession(candidate); + delete(candidate); } else if (createTime.plus(Duration.ofDays(1)).isBefore(clock.instant())) { // Sessions with state ACTIVATE, but which are not actually active Optional<ApplicationId> applicationId = candidate.getOptionalApplicationId(); if (applicationId.isEmpty()) continue; Long activeSession = activeSessions.get(applicationId.get()); if (activeSession == null || activeSession != candidate.getSessionId()) { - deleteLocalSession(candidate); + delete(candidate); log.log(Level.INFO, "Deleted inactive session " + candidate.getSessionId() + " created " + createTime + " for '" + applicationId + "'"); } @@ -484,11 +433,11 @@ public class SessionRepository { log.log(Level.FINE, () -> "Done purging old sessions"); } - private boolean hasExpired(LocalSession candidate) { - return (candidate.getCreateTime().plus(sessionLifetime).isBefore(clock.instant())); + private boolean hasExpired(Session candidate) { + return candidate.getCreateTime().plus(sessionLifetime).isBefore(clock.instant()); } - private boolean isActiveSession(LocalSession candidate) { + private boolean isActiveSession(Session candidate) { return candidate.getStatus() == Session.Status.ACTIVATE; } @@ -515,10 +464,10 @@ public class SessionRepository { return FilesApplicationPackage.fromFileWithDeployData(configApplicationDir, deployData); } - private LocalSession createSessionFromApplication(File applicationFile, - ApplicationId applicationId, - boolean internalRedeploy, - TimeoutBudget timeoutBudget) { + private Session createSessionFromApplication(File applicationFile, + ApplicationId applicationId, + boolean internalRedeploy, + TimeoutBudget timeoutBudget) { long sessionId = getNextSessionId(); try { ensureSessionPathDoesNotExist(sessionId); @@ -527,9 +476,9 @@ public class SessionRepository { SessionZooKeeperClient sessionZKClient = createSessionZooKeeperClient(sessionId); sessionZKClient.createNewSession(clock.instant()); Curator.CompletionWaiter waiter = sessionZKClient.getUploadWaiter(); - LocalSession session = new LocalSession(tenantName, sessionId, app, sessionZKClient); + Session session = new Session(tenantName, sessionId, sessionZKClient, app); waiter.awaitCompletion(timeoutBudget.timeLeft()); - addLocalSession(session); + addSession(session); return session; } catch (Exception e) { throw new RuntimeException("Error creating session " + sessionId, e); @@ -555,8 +504,8 @@ public class SessionRepository { Optional<ApplicationSet> currentActiveApplicationSet = Optional.empty(); try { long currentActiveSessionId = applicationRepo.requireActiveSessionOf(appId); - RemoteSession currentActiveSession = getRemoteSession(currentActiveSessionId); - currentActiveApplicationSet = Optional.ofNullable(ensureApplicationLoaded(currentActiveSession)); + Session activeSession = getSession(currentActiveSessionId); + currentActiveApplicationSet = Optional.ofNullable(ensureApplicationLoaded(activeSession)); } catch (IllegalArgumentException e) { // Do nothing if we have no currently active session } @@ -590,29 +539,29 @@ public class SessionRepository { void createSessionFromId(long sessionId) { File sessionDir = getAndValidateExistingSessionAppDir(sessionId); ApplicationPackage applicationPackage = FilesApplicationPackage.fromFile(sessionDir); - createLocalSession(sessionId, applicationPackage); + createSessionWithApplicationPackage(sessionId, applicationPackage); } - void createLocalSession(long sessionId, ApplicationPackage applicationPackage) { + void createSessionWithApplicationPackage(long sessionId, ApplicationPackage applicationPackage) { SessionZooKeeperClient sessionZKClient = createSessionZooKeeperClient(sessionId); - LocalSession session = new LocalSession(tenantName, sessionId, applicationPackage, sessionZKClient); - addLocalSession(session); + Session session = new Session(tenantName, sessionId, sessionZKClient, applicationPackage); + addSession(session); } /** - * Returns a new local session for the given session id if it does not already exist. - * Will also add the session to the local session cache if necessary + * Returns a new session for the given session id if it does not already exist. + * Will also add the session to the session cache if necessary */ - public void createLocalSessionFromDistributedApplicationPackage(long sessionId) { + public void createSessionFromDistributedApplicationPackage(long sessionId) { if (applicationRepo.sessionExistsInFileSystem(sessionId)) { - log.log(Level.FINE, () -> "Local session for session id " + sessionId + " already exists"); + log.log(Level.FINE, () -> "Session " + sessionId + " already exists"); createSessionFromId(sessionId); return; } SessionZooKeeperClient sessionZKClient = createSessionZooKeeperClient(sessionId); FileReference fileReference = sessionZKClient.readApplicationPackageReference(); - log.log(Level.FINE, () -> "File reference for session id " + sessionId + ": " + fileReference); + log.log(Level.FINE, () -> "File reference for session " + sessionId + ": " + fileReference); if (fileReference != null) { File rootDir = new File(Defaults.getDefaults().underVespaHome(componentRegistry.getConfigserverConfig().fileReferencesDir())); File sessionDir; @@ -622,13 +571,18 @@ public class SessionRepository { } catch (IllegalArgumentException e) { // We cannot be guaranteed that the file reference exists (it could be that it has not // been downloaded yet), and e.g when bootstrapping we cannot throw an exception in that case - log.log(Level.FINE, "File reference for session id " + sessionId + ": " + fileReference + " not found in " + fileDirectory); + log.log(Level.FINE, "File reference for session " + sessionId + ": " + fileReference + " not found in " + fileDirectory); return; } ApplicationId applicationId = sessionZKClient.readApplicationId() .orElseThrow(() -> new RuntimeException("Could not find application id for session " + sessionId)); - log.log(Level.FINE, () -> "Creating local session for tenant '" + tenantName + "' with session id " + sessionId); - createLocalSession(sessionDir, applicationId, sessionId); + log.log(Level.FINE, () -> "Creating session for tenant '" + tenantName + "' with id " + sessionId); + try { + ApplicationPackage applicationPackage = createApplicationPackage(sessionDir, applicationId, sessionId, false); + createSessionWithApplicationPackage(sessionId, applicationPackage); + } catch (Exception e) { + throw new RuntimeException("Error creating session " + sessionId, e); + } } } @@ -668,20 +622,20 @@ public class SessionRepository { return new TenantFileSystemDirs(componentRegistry.getConfigServerDB(), tenantName).getUserApplicationDir(sessionId); } - private void updateSessionStateWatcher(long sessionId, RemoteSession remoteSession) { + private void updateSessionStateWatcher(long sessionId, Session session) { SessionStateWatcher sessionStateWatcher = sessionStateWatchers.get(sessionId); if (sessionStateWatcher == null) { Curator.FileCache fileCache = curator.createFileCache(getSessionStatePath(sessionId).getAbsolute(), false); fileCache.addListener(this::nodeChanged); - sessionStateWatchers.put(sessionId, new SessionStateWatcher(fileCache, remoteSession, metrics, zkWatcherExecutor, this)); + sessionStateWatchers.put(sessionId, new SessionStateWatcher(fileCache, session, metrics, zkWatcherExecutor, this)); } else { - sessionStateWatcher.updateRemoteSession(remoteSession); + sessionStateWatcher.updateRemoteSession(session); } } @Override public String toString() { - return getLocalSessions().toString(); + return getSessions().toString(); } public Clock clock() { return clock; } @@ -707,14 +661,14 @@ public class SessionRepository { } private void checkForRemovedSessions(List<Long> sessions) { - for (Session session : remoteSessionCache.values()) + for (Session session : sessionCache.values()) if ( ! sessions.contains(session.getSessionId())) sessionRemoved(session.getSessionId()); } private void checkForAddedSessions(List<Long> sessions) { for (Long sessionId : sessions) - if (remoteSessionCache.get(sessionId) == null) + if (sessionCache.get(sessionId) == null) sessionAdded(sessionId); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionStateWatcher.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionStateWatcher.java index 0f433f53c77..f1100b37912 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionStateWatcher.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionStateWatcher.java @@ -24,13 +24,13 @@ public class SessionStateWatcher { private static final Logger log = Logger.getLogger(SessionStateWatcher.class.getName()); private final Curator.FileCache fileCache; - private volatile RemoteSession session; + private volatile Session session; private final MetricUpdater metrics; private final Executor zkWatcherExecutor; private final SessionRepository sessionRepository; SessionStateWatcher(Curator.FileCache fileCache, - RemoteSession session, + Session session, MetricUpdater metrics, Executor zkWatcherExecutor, SessionRepository sessionRepository) { @@ -51,7 +51,7 @@ public class SessionStateWatcher { break; case PREPARE: createLocalSession(sessionId); - sessionRepository.prepareRemoteSession(session); + sessionRepository.prepare(session); break; case ACTIVATE: createLocalSession(sessionId); @@ -66,7 +66,7 @@ public class SessionStateWatcher { } private void createLocalSession(long sessionId) { - sessionRepository.createLocalSessionFromDistributedApplicationPackage(sessionId); + sessionRepository.createSessionFromDistributedApplicationPackage(sessionId); } public long getSessionId() { @@ -100,7 +100,7 @@ public class SessionStateWatcher { }); } - public synchronized void updateRemoteSession(RemoteSession session) { + public synchronized void updateRemoteSession(Session session) { this.session = session; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SilentDeployLogger.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SilentDeployLogger.java index 9e2e5ddf698..e9d5a7da549 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SilentDeployLogger.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SilentDeployLogger.java @@ -7,7 +7,7 @@ import java.util.logging.Logger; import com.yahoo.config.application.api.DeployLogger; /** - * The purpose of this is to mute the log messages from model and application building in {@link RemoteSession} that + * The purpose of this is to mute the log messages from model and application building that * is triggered by {@link SessionStateWatcher}, since those messages already have been emitted by the prepare * handler, for the same prepare operation. * |