/******************************************************************************* * * Copyright (c) 2004-2009 Oracle Corporation. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Kohsuke Kawaguchi * * *******************************************************************************/ package hudson.model; /** * Represents things that {@link Queue.Executable} uses while running. * * <p> This is used in {@link Queue} to support basic mutual exclusion/locks. If * two {@link Queue.Task}s require the same {@link Resource}, they will not be * run at the same time. * * <p> Resources are compared by using their {@link #displayName names}, and * need not have the "same object" semantics. * * @since 1.121 */ public final class Resource { /** * Human-readable name of this resource. Used for rendering HTML. */ //TODO: review and check whether we can do it private public final String displayName; /** * Parent resource. * * <p> A child resource is considered a part of the parent resource, so * acquiring the parent resource always imply acquiring all the child * resources. */ //TODO: review and check whether we can do it private public final Resource parent; /** * Maximum number of concurrent write. */ //TODO: review and check whether we can do it private public final int numConcurrentWrite; public Resource(Resource parent, String displayName) { this(parent, displayName, 1); } /** * @since 1.155 */ public Resource(Resource parent, String displayName, int numConcurrentWrite) { if (numConcurrentWrite < 1) { throw new IllegalArgumentException(); } this.parent = parent; this.displayName = displayName; this.numConcurrentWrite = numConcurrentWrite; } public Resource(String displayName) { this(null, displayName); } public String getDisplayName() { return displayName; } public Resource getParent() { return parent; } public int getNumConcurrentWrite() { return numConcurrentWrite; } /** * Checks the resource collision. * * @param count If we are testing W/W conflict, total # of write counts. For * R/W conflict test, this value should be set to {@link Integer#MAX_VALUE}. */ public boolean isCollidingWith(Resource that, int count) { assert that != null; for (Resource r = that; r != null; r = r.parent) { if (this.equals(r) && r.numConcurrentWrite < count) { return true; } } for (Resource r = this; r != null; r = r.parent) { if (that.equals(r) && r.numConcurrentWrite < count) { return true; } } return false; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Resource that = (Resource) o; return displayName.equals(that.displayName) && eq(this.parent, that.parent); } private static boolean eq(Object lhs, Object rhs) { if (lhs == rhs) { return true; } if (lhs == null || rhs == null) { return false; } return lhs.equals(rhs); } @Override public int hashCode() { return displayName.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(); if (parent != null) { buf.append(parent).append('/'); } buf.append(displayName).append('(').append(numConcurrentWrite).append(')'); return buf.toString(); } }