use of com.yahoo.transaction.Mutex in project vespa by vespa-engine.
the class NodeRepository method removeRecursively.
private List<Node> removeRecursively(Node node, boolean force) {
try (Mutex lock = lockUnallocated()) {
List<Node> removed = !node.type().isDockerHost() ? new ArrayList<>() : getChildNodes(node.hostname()).stream().filter(child -> force || verifyRemovalIsAllowed(child, true)).collect(Collectors.toList());
if (force || verifyRemovalIsAllowed(node, false))
removed.add(node);
db.removeNodes(removed);
return removed;
} catch (RuntimeException e) {
throw new IllegalArgumentException("Failed to delete " + node.hostname(), e);
}
}
use of com.yahoo.transaction.Mutex in project vespa by vespa-engine.
the class ApplicationMaintainer method deployWithLock.
/**
* Redeploy this application. A lock will be taken for the duration of the deployment activation
*/
final void deployWithLock(ApplicationId application) {
// Lock is acquired with a low timeout to reduce the chance of colliding with an external deployment.
try (Mutex lock = nodeRepository().lock(application, Duration.ofSeconds(1))) {
// became inactive since deployment was requested
if (!isActive(application))
return;
Optional<Deployment> deployment = deployer.deployFromLocalActive(application);
// this will be done at another config server
if (!deployment.isPresent())
return;
deployment.get().activate();
} catch (RuntimeException e) {
log.log(Level.WARNING, "Exception on maintenance redeploy", e);
}
}
use of com.yahoo.transaction.Mutex in project vespa by vespa-engine.
the class NodeFailer method maintain.
@Override
protected void maintain() {
// Ready nodes
try (Mutex lock = nodeRepository().lockUnallocated()) {
updateNodeLivenessEventsForReadyNodes();
getReadyNodesByFailureReason().forEach((node, reason) -> {
if (!throttle(node)) {
nodeRepository().fail(node.hostname(), Agent.system, reason);
}
});
}
// Active nodes
for (Node node : determineActiveNodeDownStatus()) {
Instant graceTimeEnd = node.history().event(History.Event.Type.down).get().at().plus(downTimeLimit);
if (graceTimeEnd.isBefore(clock.instant()) && !applicationSuspended(node) && failAllowedFor(node.type()))
if (!throttle(node))
failActive(node, "Node has been down longer than " + downTimeLimit);
}
}
use of com.yahoo.transaction.Mutex in project vespa by vespa-engine.
the class NodeRetirer method retireUnallocated.
/**
* Retires unallocated nodes by moving them directly to parked.
* Returns true iff all there are no unallocated nodes that match the retirement policy
*/
boolean retireUnallocated() {
try (Mutex lock = nodeRepository().lockUnallocated()) {
List<Node> allNodes = nodeRepository().getNodes(NodeType.tenant);
Map<Flavor, Map<Node.State, Long>> numSpareNodesByFlavorByState = getNumberOfNodesByFlavorByNodeState(allNodes);
flavorSpareChecker.updateReadyAndActiveCountsByFlavor(numSpareNodesByFlavorByState);
long numFlavorsWithUnsuccessfullyRetiredNodes = allNodes.stream().filter(node -> node.state() == Node.State.ready).filter(node -> retirementPolicy.shouldRetire(node).isPresent()).collect(Collectors.groupingBy(Node::flavor, Collectors.toSet())).entrySet().stream().filter(entry -> {
Set<Node> nodesThatShouldBeRetiredForFlavor = entry.getValue();
for (Iterator<Node> iter = nodesThatShouldBeRetiredForFlavor.iterator(); iter.hasNext(); ) {
Node nodeToRetire = iter.next();
if (!flavorSpareChecker.canRetireUnallocatedNodeWithFlavor(nodeToRetire.flavor()))
break;
retirementPolicy.shouldRetire(nodeToRetire).ifPresent(reason -> {
nodeRepository().write(nodeToRetire.with(nodeToRetire.status().withWantToDeprovision(true)));
nodeRepository().park(nodeToRetire.hostname(), Agent.NodeRetirer, reason);
iter.remove();
});
}
if (!nodesThatShouldBeRetiredForFlavor.isEmpty()) {
String commaSeparatedHostnames = nodesThatShouldBeRetiredForFlavor.stream().map(Node::hostname).collect(Collectors.joining(", "));
log.info(String.format("Failed to retire %s, wanted to retire %d nodes (%s), but there are no spare nodes left.", entry.getKey(), nodesThatShouldBeRetiredForFlavor.size(), commaSeparatedHostnames));
}
return !nodesThatShouldBeRetiredForFlavor.isEmpty();
}).count();
return numFlavorsWithUnsuccessfullyRetiredNodes == 0;
}
}
use of com.yahoo.transaction.Mutex in project vespa by vespa-engine.
the class NodeRepository method performOn.
/**
* Performs an operation requiring locking on all nodes matching some filter.
*
* @param filter the filter determining the set of nodes where the operation will be performed
* @param action the action to perform
* @return the set of nodes on which the action was performed, as they became as a result of the operation
*/
private List<Node> performOn(NodeFilter filter, UnaryOperator<Node> action) {
List<Node> unallocatedNodes = new ArrayList<>();
ListMap<ApplicationId, Node> allocatedNodes = new ListMap<>();
// Group matching nodes by the lock needed
for (Node node : db.getNodes()) {
if (!filter.matches(node))
continue;
if (node.allocation().isPresent())
allocatedNodes.put(node.allocation().get().owner(), node);
else
unallocatedNodes.add(node);
}
// perform operation while holding locks
List<Node> resultingNodes = new ArrayList<>();
try (Mutex lock = lockUnallocated()) {
for (Node node : unallocatedNodes) resultingNodes.add(action.apply(node));
}
for (Map.Entry<ApplicationId, List<Node>> applicationNodes : allocatedNodes.entrySet()) {
try (Mutex lock = lock(applicationNodes.getKey())) {
for (Node node : applicationNodes.getValue()) resultingNodes.add(action.apply(node));
}
}
return resultingNodes;
}
Aggregations