diff options
Diffstat (limited to 'configserver/src/main/java')
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java | 10 | ||||
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java | 6 | ||||
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionStateWatcher.java | 74 | ||||
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionStateWatcher.java (renamed from configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionStateWatcher.java) | 51 | ||||
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java | 2 | ||||
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java | 34 | ||||
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/session/SilentDeployLogger.java | 2 | ||||
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java | 4 |
8 files changed, 120 insertions, 63 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 becf01c191c..c44a839d24d 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 @@ -490,7 +490,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye Tenant tenant = tenantRepository.getTenant(applicationId.tenant()); if (tenant == null) throw new NotFoundException("Tenant '" + applicationId.tenant() + "' not found"); long sessionId = getSessionIdForApplication(tenant, applicationId); - RemoteSession session = tenant.getSessionRepository().getRemoteSession(sessionId); + RemoteSession session = tenant.getSessionRepo().getRemoteSession(sessionId); if (session == null) throw new NotFoundException("Remote session " + sessionId + " not found"); return session.ensureApplicationLoaded().getForVersionOrLatest(version, clock.instant()); } catch (NotFoundException e) { @@ -528,7 +528,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye } private boolean localSessionHasBeenDeleted(ApplicationId applicationId, long sessionId, Duration waitTime) { - SessionRepository sessionRepository = tenantRepository.getTenant(applicationId.tenant()).getSessionRepository(); + SessionRepository sessionRepository = tenantRepository.getTenant(applicationId.tenant()).getSessionRepo(); Instant end = Instant.now().plus(waitTime); do { if (sessionRepository.getRemoteSession(sessionId) == null) return true; @@ -690,7 +690,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye public int deleteExpiredRemoteSessions(Clock clock, Duration expiryTime) { return tenantRepository.getAllTenants() .stream() - .map(tenant -> tenant.getSessionRepository().deleteExpiredRemoteSessions(clock, expiryTime)) + .map(tenant -> tenant.getSessionRepo().deleteExpiredRemoteSessions(clock, expiryTime)) .mapToInt(i -> i) .sum(); } @@ -765,7 +765,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye } private RemoteSession getRemoteSession(Tenant tenant, long sessionId) { - RemoteSession session = tenant.getSessionRepository().getRemoteSession(sessionId); + RemoteSession session = tenant.getSessionRepo().getRemoteSession(sessionId); if (session == null) throw new NotFoundException("Session " + sessionId + " was not found"); return session; @@ -816,7 +816,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye private RemoteSession getActiveSession(Tenant tenant, ApplicationId applicationId) { TenantApplications applicationRepo = tenant.getApplicationRepo(); if (applicationRepo.activeApplications().contains(applicationId)) { - return tenant.getSessionRepository().getRemoteSession(applicationRepo.requireActiveSessionOf(applicationId)); + return tenant.getSessionRepo().getRemoteSession(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 0fb1407830a..def629f738c 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 @@ -63,10 +63,10 @@ public class Deployment implements com.yahoo.config.provision.Deployment { /** The (optional) Athenz domain this application should use */ private final Optional<AthenzDomain> athenzDomain; - /** Whether this model should be validated (only takes effect if prepared=false) */ - private final boolean validate; - private boolean prepared = false; + + /** Whether this model should be validated (only takes effect if prepared=false) */ + private boolean validate; private boolean ignoreSessionStaleFailure = false; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionStateWatcher.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionStateWatcher.java new file mode 100644 index 00000000000..acbb1dc81ce --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSessionStateWatcher.java @@ -0,0 +1,74 @@ +// 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.session; + +import java.util.logging.Level; +import com.yahoo.text.Utf8; +import com.yahoo.vespa.curator.Curator; +import org.apache.curator.framework.recipes.cache.ChildData; + +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +/** + * Watches one particular local session (/config/v2/tenants/<tenantName>/sessions/<n>/sessionState in ZooKeeper) + * to pick up when an application is deleted (the delete might be done on any config server in the cluster) + * + * @author Harald Musum + */ +public class LocalSessionStateWatcher { + + private static final Logger log = Logger.getLogger(LocalSessionStateWatcher.class.getName()); + + private final Curator.FileCache fileCache; + private final LocalSession session; + private final SessionRepository sessionRepository; + private final Executor zkWatcherExecutor; + + LocalSessionStateWatcher(Curator.FileCache fileCache, LocalSession session, + SessionRepository sessionRepository, Executor zkWatcherExecutor) { + this.fileCache = fileCache; + this.session = session; + this.sessionRepository = sessionRepository; + this.zkWatcherExecutor = zkWatcherExecutor; + this.fileCache.start(); + this.fileCache.addListener(this::nodeChanged); + } + + // Will delete session if it exists in local session repo + private void sessionChanged(Session.Status status) { + long sessionId = session.getSessionId(); + log.log(status == Session.Status.DELETE ? Level.INFO : Level.FINE, + session.logPre() + "Session change: Local session " + sessionId + " changed status to " + status); + + if (status.equals(Session.Status.DELETE) && sessionRepository.getLocalSession(sessionId) != null) { + log.log(Level.FINE, session.logPre() + "Deleting session " + sessionId); + sessionRepository.deleteLocalSession(session); + } + } + + public long getSessionId() { + return session.getSessionId(); + } + + public void close() { + try { + fileCache.close(); + } catch (Exception e) { + log.log(Level.WARNING, "Exception when closing watcher", e); + } + } + + public void nodeChanged() { + zkWatcherExecutor.execute(() -> { + try { + ChildData node = fileCache.getCurrentData(); + if (node != null) { + sessionChanged(Session.Status.parse(Utf8.toString(node.getData()))); + } + } catch (Exception e) { + log.log(Level.WARNING, session.logPre() + "Error handling session changed for session " + getSessionId(), e); + } + }); + } + +} 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/RemoteSessionStateWatcher.java index 14f2ef6f271..68345d3862d 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/RemoteSessionStateWatcher.java @@ -1,7 +1,6 @@ // 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 java.util.Optional; import java.util.logging.Level; import com.yahoo.text.Utf8; import com.yahoo.vespa.config.server.ReloadHandler; @@ -17,61 +16,47 @@ import java.util.logging.Logger; * The session must be in the session repo. * * @author Vegard Havdal - * @author hmusum */ -public class SessionStateWatcher { +public class RemoteSessionStateWatcher { - private static final Logger log = Logger.getLogger(SessionStateWatcher.class.getName()); + private static final Logger log = Logger.getLogger(RemoteSessionStateWatcher.class.getName()); private final Curator.FileCache fileCache; private final ReloadHandler reloadHandler; - private final RemoteSession remoteSession; - private final Optional<LocalSession> localSession; + private final RemoteSession session; private final MetricUpdater metrics; private final Executor zkWatcherExecutor; - private final SessionRepository sessionRepository; - SessionStateWatcher(Curator.FileCache fileCache, - ReloadHandler reloadHandler, - RemoteSession remoteSession, - Optional<LocalSession> localSession, - MetricUpdater metrics, - Executor zkWatcherExecutor, - SessionRepository sessionRepository) { + RemoteSessionStateWatcher(Curator.FileCache fileCache, + ReloadHandler reloadHandler, + RemoteSession session, + MetricUpdater metrics, + Executor zkWatcherExecutor) { this.fileCache = fileCache; this.reloadHandler = reloadHandler; - this.remoteSession = remoteSession; - this.localSession = localSession; + this.session = session; this.metrics = metrics; this.fileCache.start(); this.fileCache.addListener(this::nodeChanged); this.zkWatcherExecutor = zkWatcherExecutor; - this.sessionRepository = sessionRepository; } private void sessionChanged(Session.Status status) { - long sessionId = remoteSession.getSessionId(); - // valid for NEW -> PREPARE transitions, not ACTIVATE -> PREPARE. if (status.equals(Session.Status.PREPARE)) { - log.log(Level.FINE, remoteSession.logPre() + "Loading prepared session: " + remoteSession.getSessionId()); - remoteSession.loadPrepared(); + log.log(Level.FINE, session.logPre() + "Loading prepared session: " + session.getSessionId()); + session.loadPrepared(); } else if (status.equals(Session.Status.ACTIVATE)) { - remoteSession.makeActive(reloadHandler); + session.makeActive(reloadHandler); } else if (status.equals(Session.Status.DEACTIVATE)) { - remoteSession.deactivate(); + session.deactivate(); } else if (status.equals(Session.Status.DELETE)) { - remoteSession.deactivate(); - log.log(Level.INFO, remoteSession.logPre() + "Session change: Local session " + sessionId + " changed status to " + status); - localSession.ifPresent(session -> { - log.log(Level.FINE, session.logPre() + "Deleting session " + sessionId); - sessionRepository.deleteLocalSession(session); - }); + session.deactivate(); } } public long getSessionId() { - return remoteSession.getSessionId(); + return session.getSessionId(); } public void close() { @@ -84,18 +69,18 @@ public class SessionStateWatcher { private void nodeChanged() { zkWatcherExecutor.execute(() -> { - Session.Status currentStatus = remoteSession.getStatus(); + Session.Status currentStatus = session.getStatus(); Session.Status newStatus = Session.Status.NONE; try { ChildData node = fileCache.getCurrentData(); if (node != null) { newStatus = Session.Status.parse(Utf8.toString(node.getData())); - log.log(Level.FINE, remoteSession.logPre() + "Session change: Remote session " + remoteSession.getSessionId() + + log.log(Level.FINE, session.logPre() + "Session change: Remote session " + session.getSessionId() + " changed status from " + currentStatus.name() + " to " + newStatus.name()); sessionChanged(newStatus); } } catch (Exception e) { - log.log(Level.WARNING, remoteSession.logPre() + "Error handling session change from " + currentStatus.name() + + log.log(Level.WARNING, session.logPre() + "Error handling session change from " + currentStatus.name() + " to " + newStatus.name() + " for session " + getSessionId(), e); metrics.incSessionChangeErrors(); } 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 77058d8d6d9..1e832548342 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 @@ -20,7 +20,6 @@ import java.util.Optional; * system ({@link LocalSession}s) and sessions working on zookeeper {@link RemoteSession}s. * * @author Ulf Lilleengen - * @author hmusum */ public abstract class Session implements Comparable<Session> { @@ -33,7 +32,6 @@ public abstract class Session implements Comparable<Session> { this.sessionId = sessionId; this.sessionZooKeeperClient = sessionZooKeeperClient; } - /** * Retrieve the session id for this session. * @return the session id. 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 392c5e93122..c7dc295c42d 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 @@ -72,7 +72,8 @@ public class SessionRepository { private final SessionCache<LocalSession> localSessionCache = new SessionCache<>(); private final SessionCache<RemoteSession> remoteSessionCache = new SessionCache<>(); - private final Map<Long, SessionStateWatcher> sessionStateWatchers = new HashMap<>(); + private final Map<Long, LocalSessionStateWatcher> localSessionStateWatchers = new HashMap<>(); + private final Map<Long, RemoteSessionStateWatcher> remoteSessionStateWatchers = new HashMap<>(); private final Duration sessionLifetime; private final Clock clock; private final Curator curator; @@ -119,11 +120,10 @@ public class SessionRepository { public synchronized void addSession(LocalSession session) { localSessionCache.addSession(session); + Path sessionsPath = TenantRepository.getSessionsPath(session.getTenantName()); long sessionId = session.getSessionId(); - Curator.FileCache fileCache = curator.createFileCache(getSessionStatePath(sessionId).getAbsolute(), false); - RemoteSession remoteSession = new RemoteSession(tenantName, sessionId, componentRegistry, createSessionZooKeeperClient(sessionId)); - sessionStateWatchers.put(sessionId, new SessionStateWatcher(fileCache, reloadHandler, remoteSession, - Optional.of(session), metrics, zkWatcherExecutor, this)); + Curator.FileCache fileCache = curator.createFileCache(sessionsPath.append(String.valueOf(sessionId)).append(ConfigCurator.SESSIONSTATE_ZK_SUBPATH).getAbsolute(), false); + localSessionStateWatchers.put(sessionId, new LocalSessionStateWatcher(fileCache, session, this, zkWatcherExecutor)); } public LocalSession getLocalSession(long sessionId) { @@ -208,7 +208,7 @@ public class SessionRepository { public void deleteLocalSession(LocalSession session) { long sessionId = session.getSessionId(); log.log(Level.FINE, "Deleting local session " + sessionId); - SessionStateWatcher watcher = sessionStateWatchers.remove(sessionId); + LocalSessionStateWatcher watcher = localSessionStateWatchers.remove(sessionId); if (watcher != null) watcher.close(); localSessionCache.removeSession(sessionId); NestedTransaction transaction = new NestedTransaction(); @@ -318,22 +318,21 @@ public class SessionRepository { */ public void sessionAdded(long sessionId) { log.log(Level.FINE, () -> "Adding session to SessionRepository: " + sessionId); - RemoteSession remoteSession = createRemoteSession(sessionId); - Curator.FileCache fileCache = curator.createFileCache(getSessionStatePath(sessionId).getAbsolute(), false); + RemoteSession session = createRemoteSession(sessionId); + Path sessionPath = sessionsPath.append(String.valueOf(sessionId)); + Curator.FileCache fileCache = curator.createFileCache(sessionPath.append(ConfigCurator.SESSIONSTATE_ZK_SUBPATH).getAbsolute(), false); fileCache.addListener(this::nodeChanged); - loadSessionIfActive(remoteSession); - addRemoteSession(remoteSession); - Optional<LocalSession> localSession = Optional.empty(); + loadSessionIfActive(session); + addRemoteSession(session); + remoteSessionStateWatchers.put(sessionId, new RemoteSessionStateWatcher(fileCache, reloadHandler, session, metrics, zkWatcherExecutor)); if (distributeApplicationPackage.value()) { - localSession = createLocalSessionUsingDistributedApplicationPackage(sessionId); + Optional<LocalSession> localSession = createLocalSessionUsingDistributedApplicationPackage(sessionId); localSession.ifPresent(this::addSession); } - sessionStateWatchers.put(sessionId, new SessionStateWatcher(fileCache, reloadHandler, remoteSession, localSession, - metrics, zkWatcherExecutor, this)); } private void sessionRemoved(long sessionId) { - SessionStateWatcher watcher = sessionStateWatchers.remove(sessionId); + RemoteSessionStateWatcher watcher = remoteSessionStateWatchers.remove(sessionId); if (watcher != null) watcher.close(); remoteSessionCache.removeSession(sessionId); metrics.incRemovedSessions(); @@ -572,13 +571,10 @@ public class SessionRepository { return new SessionCounter(componentRegistry.getConfigCurator(), tenantName).nextSessionId(); } - public Path getSessionPath(long sessionId) { + private Path getSessionPath(long sessionId) { return sessionsPath.append(String.valueOf(sessionId)); } - Path getSessionStatePath(long sessionId) { - return getSessionPath(sessionId).append(ConfigCurator.SESSIONSTATE_ZK_SUBPATH); - } private SessionZooKeeperClient createSessionZooKeeperClient(long sessionId) { String serverId = componentRegistry.getConfigserverConfig().serverId(); 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 445837104d4..92ab6b3fbf5 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 is triggered by {@link SessionStateWatcher}, since those messages already + * The purpose of this is to mute the log messages from model and application building in {@link RemoteSession} that is triggered by {@link RemoteSessionStateWatcher}, since those messages already * have been emitted by the prepare handler, for the same prepare operation. * * @author vegardh diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java index cbcb96d0b36..f7c8ae9d5c3 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenant.java @@ -66,6 +66,10 @@ public class Tenant implements TenantHandlerProvider { return requestHandler; } + public SessionRepository getSessionRepo() { + return sessionRepository; + } + public TenantName getName() { return name; } |