diff options
Diffstat (limited to 'configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java')
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java | 100 |
1 files changed, 80 insertions, 20 deletions
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 index ed401e65f20..36cac87a326 100644 --- 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 @@ -1,11 +1,22 @@ // 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.AllocatedHosts; import com.yahoo.config.provision.TenantName; +import com.yahoo.lang.SettableOptional; import com.yahoo.transaction.Transaction; +import com.yahoo.vespa.config.server.GlobalComponentRegistry; import com.yahoo.vespa.config.server.application.ApplicationSet; +import com.yahoo.vespa.config.server.modelfactory.ActivatedModelsBuilder; +import com.yahoo.vespa.curator.Curator; +import org.apache.zookeeper.KeeperException; +import java.time.Clock; import java.util.Optional; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; /** * A RemoteSession represents a session created on another config server. This session can @@ -15,46 +26,95 @@ import java.util.Optional; */ public class RemoteSession extends Session { - private final Optional<ApplicationSet> applicationSet; + private static final Logger log = Logger.getLogger(RemoteSession.class.getName()); + private ApplicationSet applicationSet = null; + private final ActivatedModelsBuilder applicationLoader; + private final Clock clock; /** - * Creates a remote session, no application set loaded + * 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 componentRegistry a registry of global components * @param zooKeeperClient a SessionZooKeeperClient instance */ public RemoteSession(TenantName tenant, long sessionId, + GlobalComponentRegistry componentRegistry, SessionZooKeeperClient zooKeeperClient) { - this(tenant, sessionId, zooKeeperClient, Optional.empty()); + super(tenant, sessionId, zooKeeperClient); + this.applicationLoader = new ActivatedModelsBuilder(tenant, sessionId, zooKeeperClient, componentRegistry); + this.clock = componentRegistry.getClock(); } - /** - * 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 - */ - public RemoteSession(TenantName tenant, - long sessionId, - SessionZooKeeperClient zooKeeperClient, - Optional<ApplicationSet> applicationSet) { - super(tenant, sessionId, zooKeeperClient); - this.applicationSet = applicationSet; + void prepare() { + Curator.CompletionWaiter waiter = sessionZooKeeperClient.getPrepareWaiter(); + ensureApplicationLoaded(); + notifyCompletion(waiter); } - Optional<ApplicationSet> applicationSet() { - return applicationSet; + private ApplicationSet loadApplication() { + ApplicationPackage applicationPackage = sessionZooKeeperClient.loadApplicationPackage(); + + // Read hosts allocated on the config server instance which created this + Optional<AllocatedHosts> allocatedHosts = applicationPackage.getAllocatedHosts(); + + return ApplicationSet.fromList(applicationLoader.buildModels(getApplicationId(), + sessionZooKeeperClient.readDockerImageRepository(), + sessionZooKeeperClient.readVespaVersion(), + applicationPackage, + new SettableOptional<>(allocatedHosts), + clock.instant())); } - public synchronized RemoteSession deactivated() { - return new RemoteSession(tenant, sessionId, sessionZooKeeperClient, Optional.empty()); + public synchronized ApplicationSet ensureApplicationLoaded() { + return applicationSet == null ? applicationSet = loadApplication() : applicationSet; + } + + public synchronized void deactivate() { + applicationSet = null; } public Transaction createDeleteTransaction() { return sessionZooKeeperClient.createWriteStatusTransaction(Status.DELETE); } + + void confirmUpload() { + Curator.CompletionWaiter waiter = sessionZooKeeperClient.getUploadWaiter(); + log.log(Level.FINE, "Notifying upload waiter for session " + getSessionId()); + notifyCompletion(waiter); + log.log(Level.FINE, "Done notifying upload for session " + getSessionId()); + } + + void notifyCompletion(Curator.CompletionWaiter completionWaiter) { + try { + completionWaiter.notifyCompletion(); + } catch (RuntimeException e) { + // Throw only if we get something else than NoNodeException or NodeExistsException. + // NoNodeException might happen when the session is no longer in use (e.g. the app using this session + // has been deleted) and this method has not been called yet for the previous session operation on a + // minority of the config servers. + // NodeExistsException might happen if an event for this node is delivered more than once, in that case + // this is a no-op + Set<Class<? extends KeeperException>> acceptedExceptions = Set.of(KeeperException.NoNodeException.class, + KeeperException.NodeExistsException.class); + Class<? extends Throwable> exceptionClass = e.getCause().getClass(); + if (acceptedExceptions.contains(exceptionClass)) + log.log(Level.FINE, "Not able to notify completion for session " + getSessionId() + + " (" + completionWaiter + ")," + + " node " + (exceptionClass.equals(KeeperException.NoNodeException.class) + ? "has been deleted" + : "already exists")); + else + throw e; + } + } + + public void delete() { + Transaction transaction = sessionZooKeeperClient.deleteTransaction(); + transaction.commit(); + transaction.close(); + } } |