提交 76ecee17 编写于 作者: L lei.yul 提交者: yulei

[Misc] Resource Management API

Summary:
Introduce ResourceContainer to manage resources.
ResourceContainer defines a set of resource Constraint
that limit resource usage by threads.

Test Plan: jtreg com/alibaba/rcm

Reviewed-by: luchsh, sanhong

Issue: alibaba/dragonwell8#87
上级 fbd31ae6
......@@ -559,7 +559,8 @@ EXPORTED_PRIVATE_PKGS = com.oracle.net \
com.oracle.nio \
com.alibaba.jwarmup \
com.alibaba.management \
com.alibaba.jvm.gc
com.alibaba.jvm.gc \
com.alibaba.rcm
$(IMAGES_OUTPUTDIR)/symbols/_the.symbols: $(IMAGES_OUTPUTDIR)/lib/rt.jar
$(RM) -r $(IMAGES_OUTPUTDIR)/symbols/META-INF/sym
......
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package com.alibaba.rcm;
import java.util.Arrays;
/**
* A {@code Constraint} is a pair of {@link ResourceType} and {@code values}.
* The constrained resource and specification of parameter values are documented
* in enum constants in {@link ResourceType}
* <p>
* A {@code Constraint} must be associated with one {@code ResourceType}, so we
* provide factory method {@link ResourceType#newConstraint(long...)} to implement
* this restriction. For example:
* <pre>
* Constraint cpuConstraint = ResourceType.CPU_PERCENT.newConstraint(30);
* </pre>
* <p>
* {@code ResourceContainer} and {@code Constraint} follow the one-to-many relationship.
* {@link ResourceContainer#getConstraints()} can fetch the Constraint associated with
* ResourceContainer.
*/
public class Constraint {
private final ResourceType type;
private final long[] values;
/**
* Constraint should be instantiated by {@link ResourceType#newConstraint(long...)}
*/
Constraint(ResourceType type, long[] values) {
assert type.validate(values);
this.type = type;
this.values = values;
}
/**
* Returns the currently restricted resource type.
*
* @return resource type
*/
public ResourceType getResourceType() {
return type;
}
/**
* Returns the constraint value of ResourceType described by a long[],
* which is documented on the ResourceType enums.
* <p>
* The returned value is a copy of the internal storage array to prevent
* modification.
*
* @return constraint values
*/
public long[] getValues() {
return Arrays.copyOf(values, values.length);
}
@Override
public String toString() {
return "Constraint{" +
"type=" + type +
", values=" + Arrays.toString(values) +
'}';
}
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package com.alibaba.rcm;
import com.alibaba.rcm.internal.AbstractResourceContainer;
/**
* A {@code ResourceContainer} defines a set of resource {@link Constraint}s
* that limit resource usage by threads.
* Zero or more threads can be attached to one {@code ResourceContainer}.
* <pre>
* +-------------------------------+ +-----------------------------+
* |ResourceContainer | |RootContainer |
* | | | |
* | +---------------+ | | |
* | |CPU Constraint | | | +----------+ |
* | +---------------+ <------------------+ Thread | |
* | +---------------+ | | +----------+ |
* | |Mem Constraint |command.run()| | container.run(command) |
* | +---------------+ | | | |
* | |----------------> v | | |
* | resources are command.run()| | |
* | controlled by returns | | back to root |
* | constraints +-----------------> container |
* | | | |
* | | | |
* +-------------------------------+ +-----------------------------+
* </pre>
* The figure above describes the structure and usage of {@code ResourceContainer}.
* <p>
* The main Thread is bounded to root container which can be fetched by
* {@link ResourceContainer#root()}. Root Container is the system default
* {@code ResourceContainer} without any resource restrictions.
* Newly created threads are implicitly bounded to {@code ResourceContainer}
* of the parent thread.
* <p>
* A Thread can invoke {@link ResourceContainer#run(Runnable command)} to
* attach to the {@code ResourceContainer} and run the {@code command},
* the resource usage of the thread is controlled by the {@code ResourceContainer}'s
* constraints while running the command.
* When the execution of the command is either finished normally
* or terminated by Exception, the thread will be detached from the container automatically.
* <p>
* Components of a {@code ResourceContainer} implementation:
* <ul>
* <li>{@link ResourceType}: an implementation can customize some ResourceType</li>
* <li>{@code ResourceContainer}: Implements a class extends
* {@link AbstractResourceContainer}</li>
* <li>{@link ResourceContainerFactory}: service provider </li>
* </ul>
*
* <p>
* {@code ResourceContainer} needs to be created from a set of {@code Constraint}s
* <p>
* In most cases, the following idiom should be used:
* <pre>
* ResourceContainer resourceContainer = containerFactory.createContainer(
* Arrays.asList(
* CPU_PERCENT.newConstraint(50),
* HEAP_RETAINED.newConstraint(100_000_000)
* ));
*
* resourceContainer.run(requestHandler);
*
* resourceContainer.destroy();
* </pre>
*
* @see ResourceContainerFactory
*/
public interface ResourceContainer {
/**
* An enumeration of Container state
*/
enum State {
/**
* Created but not ready for attaching (initializing).
*/
CREATED,
/**
* Ready for attaching.
*/
RUNNING,
/**
* {@link ResourceContainer#destroy()} has been called.
*/
STOPPING,
/**
* Container is destroyed. Further usage is not allowed.
*/
DEAD
}
/**
* Returns the system-wide "root" Resource container.
* <p>
* Root ResourceContainer is a <em>virtual<em/> container that indicates
* the default resource container for any thread, which is not attached
* to a ResourceContainer created by users. Root ResourceContainer does
* not have any resource constrains.
* <p>
* {@link #run(Runnable)} method of root container is a special
* implementation that detaches from the current container and returns
* to the root container.
* It is very useful in ResourceContainer switch scenario:
* <pre>
* // Assume we already attach to a non-root resourceContainer1
* resourceContainer2.run(command);
* // throws exception, because it is illegal to switch between non-root
* // ResourceContainers
* ResourceContainer.root(() -> resourceContainer2.run(command));
* </pre>
*
* @return root container
*/
static ResourceContainer root() {
return AbstractResourceContainer.root();
}
/**
* Returns the ResourceContainer associated with the current thread.
* For threads that do not attach to any user-created ResourceContainer,
* {@link #root()} is returned.
*
* @return current ResourceContainer
*/
static ResourceContainer current() {
return AbstractResourceContainer.current();
}
/**
* Returns the current ResourceContainer state.
*
* @return current state.
*/
ResourceContainer.State getState();
/**
* Attach the current thread to the ResourceContainer to run the {@code command},
* and detach the ResourceContainer when {@code command} is either normally finished
* or terminated by Exception.
* <p>
* At the same time, it is not allowed to switch directly between any two
* containers. If the switch is indeed required, the
* {@link #root()} container should be used.
* <p>
* This way restricts the container attach/detach mode for the API users,
* but is less error-prone.
*
* <pre>
* ResourceContainer resourceContainer = ....
* assert ResourceContainer.current() == ResourceContainer.root();
* resourceContainer.run(() -> {
* assert ResourceContainer.current() == resourceContainer;
* });
* assert ResourceContainer.current() == ResourceContainer.root();
* </pre>
*
* @param command the target code
*/
void run(Runnable command);
/**
* Updates {@link Constraint} of this resource container.
* <p>
* Constraints with an identical type will
* replace each other according to the calling order.
*
* @param constraint constraints list
* @throws UnsupportedOperationException {@link Constraint#getResourceType()} is not
* supported by the implementation
*/
void updateConstraint(Constraint constraint);
/**
* Gets container's {@link Constraint}s
*
* @return {@code Constraint}s
*/
Iterable<Constraint> getConstraints();
/**
* Destroys this resource container, also kills the attached threads and releases
* resources described in {@link #getConstraints()}.
* <p>
* Once this method is called, the state will become {@link State#STOPPING}.
* And the caller thread will be blocked until all the resources have been released.
* Then the container state will become {@link State#DEAD}.
*/
void destroy();
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package com.alibaba.rcm;
/**
* Factory class for {@link ResourceContainer}.
* <p>
* Each ResourceContainer implementation needs to provide a public ResourceContainerFactory
* instance to allow users to choose a specific ResourceContainer implementation:
* <pre>
* ResourceContainerFactory FACTORY_INSTANCE = new ResourceContainerFactory() {
* protected ResourceContainer createContainer(Iterable<Constraint> constraints) {
* return new AbstractResourceContainer() {
* // implement abstract methods
* }
* }
* }
* </pre>
* Then API users can create ResourceContainer by {@code FACTORY_INSTANCE.createContainer(...)}
*/
public interface ResourceContainerFactory {
/**
* Returns the system-wide default factory for this invocation of
* the Java virtual machine.
*
* @return The system-wide default factory
*/
static ResourceContainerFactory defaultFactory() {
throw new UnsupportedOperationException("NYI");
}
/**
* Builds ResourceContainer with constraints.
*
* @param constraints the target {@code Constraint}s
* @return a newly-created ResourceContainer
*/
ResourceContainer createContainer(Iterable<Constraint> constraints);
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package com.alibaba.rcm;
import java.util.Arrays;
import java.util.stream.IntStream;
/**
* Enumeration of {@link Constraint}'s type.
* <p>
* {@code class} is used instead of {@code enum} to provide extensibility.
* Implementation of resource management can define its resource type.
* Below is an example of extension ResourceType:
*
* <pre>
* public class MyResourceType extends ResourceType {
* public final static ResourceType CPU_CFS = new MyResourceType();
*
* public MyResourceType() {}
* }
* </pre>
* <p>
* CPU_CFS is an instance of {@code ResourceType}, so it can be used wherever
* ResourceType is handled.
* <p>
* The descriptions and parameters of each public final static value need to
* be documented in detail.
*/
public class ResourceType {
/**
* Throttling the CPU usage by CPU percentage.
* <p>
* param #1: CPU usage measured in a percentage granularity.
* The value ranges from 0 to CPU_COUNT * 100. For example, {@code 150}
* means that ResourceContainer can use up to 1.5 CPU cores.
*/
public final static ResourceType CPU_PERCENT =
new ResourceType("CPU_PERCENT", newChecker(0, Runtime.getRuntime().availableProcessors() * 100));
/**
* Throttling the max heap usage.
* <p>
* param #1: maximum heap size in bytes
*/
public final static ResourceType HEAP_RETAINED =
new ResourceType("HEAP_RETAINED", newChecker(0, Runtime.getRuntime().maxMemory()));
private final String name;
private final ParameterChecker[] checkers;
protected ResourceType(String name) {
this.name = name;
this.checkers = null;
}
protected ResourceType(String name, ParameterChecker... checkers) {
this.name = name;
this.checkers = checkers;
}
/**
* Creates a {@link Constraint} with this {@code ResourceType} and
* the given {@code values}.
*
* @param values constraint values
* @return newly-created Constraint
* @throws IllegalArgumentException when parameter check fails
*/
public final Constraint newConstraint(long... values) {
if (!validate(values)) {
throw new IllegalArgumentException(this +
" values: " + Arrays.toString(values));
}
return new Constraint(this, values);
}
/**
* Checks the validity of parameters. Since a long [] is used to
* express the configuration, a length and range check is required.
* <p>
* Each ResourceType instance can implement its own {@code validate()}
* method through Override, for example:
* <pre>
* public final static ResourceType MY_RESOURCE =
* new ResourceType() {
* protected boolean validate(long[] values) {
* // the check logic
* }
* };
* </pre>
*
* @param values parameter value
* @return if parameter is validated
*/
protected boolean validate(long[] values) {
if (checkers == null) {
return true;
}
if (checkers.length != values.length) {
return false;
}
return IntStream.range(0, values.length)
.allMatch(i -> checkers[i].check(values[i]));
}
@Override
public String toString() {
return name;
}
protected static ParameterChecker newChecker(long from, long to) {
return new ParameterChecker(from, to);
}
/**
* Helper class for parameter range check.
*/
protected static class ParameterChecker {
private final long from;
private final long to;
protected ParameterChecker(long from, long to) {
this.from = from;
this.to = to;
}
protected boolean check(long value) {
return value >= from && value < to;
}
}
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package com.alibaba.rcm.internal;
import com.alibaba.rcm.Constraint;
import com.alibaba.rcm.ResourceContainer;
import sun.misc.SharedSecrets;
import java.util.Collections;
/**
* A skeletal implementation of {@link ResourceContainer} that practices
* the attach/detach paradigm described in {@link ResourceContainer#run(Runnable)}.
* <p>
* Each {@code ResourceContainer} implementation must inherit from this class.
*
* @see ResourceContainer#run(Runnable)
*/
public abstract class AbstractResourceContainer implements ResourceContainer {
protected final static AbstractResourceContainer ROOT = new RootContainer();
public static AbstractResourceContainer root() {
return ROOT;
}
public static AbstractResourceContainer current() {
if (!sun.misc.VM.isBooted()) {
return root();
}
return SharedSecrets.getJavaLangAccess().getResourceContainer(Thread.currentThread());
}
@Override
public void run(Runnable command) {
if (getState() != State.RUNNING) {
throw new IllegalStateException("container not running");
}
ResourceContainer container = current();
if (container == this) {
command.run();
return;
}
if (container != root()) {
throw new IllegalStateException("must be in root container " +
"before running into non-root container.");
}
attach();
try {
command.run();
} finally {
detach();
}
}
/**
* Attach to this resource container.
* Ensure {@link ResourceContainer#current()} as a root container
* before calling this method.
* <p>
* The implementation class must call {@code super.attach()} to coordinate
* with {@link ResourceContainer#current()}
*/
protected void attach() {
SharedSecrets.getJavaLangAccess().setResourceContainer(Thread.currentThread(), this);
}
/**
* Detach from this resource container and return to root container.
* <p>
* The implementation class must call {@code super.detach()} to coordinate
* with {@link ResourceContainer#current()}
*/
protected void detach() {
SharedSecrets.getJavaLangAccess().setResourceContainer(Thread.currentThread(), root());
}
private static class RootContainer extends AbstractResourceContainer {
@Override
public void run(Runnable command) {
AbstractResourceContainer container = current();
if (container == root()) {
command.run();
return;
}
container.detach();
try {
command.run();
} finally {
container.attach();
}
}
@Override
public ResourceContainer.State getState() {
return ResourceContainer.State.RUNNING;
}
@Override
protected void attach() {
throw new UnsupportedOperationException("should not reach here");
}
@Override
protected void detach() {
throw new UnsupportedOperationException("should not reach here");
}
@Override
public void updateConstraint(Constraint constraint) {
throw new UnsupportedOperationException("updateConstraint() is not supported by root container");
}
@Override
public Iterable<Constraint> getConstraints() {
return Collections.emptyList();
}
@Override
public void destroy() {
throw new UnsupportedOperationException("destroy() is not supported by root container");
}
}
}
......@@ -37,12 +37,14 @@ import java.security.PrivilegedAction;
import java.security.AllPermission;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
import com.alibaba.rcm.internal.AbstractResourceContainer;
import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
import sun.reflect.annotation.AnnotationType;
/**
* The <code>System</code> class contains several useful class fields
* and methods. It cannot be instantiated.
......@@ -1269,6 +1271,16 @@ public final class System {
public void invokeFinalize(Object o) throws Throwable {
o.finalize();
}
@Override
public void setResourceContainer(Thread thread, AbstractResourceContainer container) {
thread.resourceContainer = container;
}
@Override
public AbstractResourceContainer getResourceContainer(Thread thread) {
return thread.resourceContainer;
}
});
}
}
......@@ -36,6 +36,7 @@ import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport;
import com.alibaba.rcm.internal.AbstractResourceContainer;
import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
......@@ -213,6 +214,10 @@ class Thread implements Runnable {
private volatile int threadStatus = 0;
/**
* The thread attached {@code ResourceContainer}
*/
AbstractResourceContainer resourceContainer;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
......@@ -423,6 +428,10 @@ class Thread implements Runnable {
/* Set thread ID */
tid = nextThreadID();
/* com.alibaba.rcm API */
this.resourceContainer = parent.resourceContainer != null ?
parent.resourceContainer : AbstractResourceContainer.root();
}
/**
......
......@@ -30,6 +30,7 @@ import java.lang.reflect.Executable;
import java.security.AccessControlContext;
import java.util.Map;
import com.alibaba.rcm.internal.AbstractResourceContainer;
import sun.reflect.ConstantPool;
import sun.reflect.annotation.AnnotationType;
import sun.nio.ch.Interruptible;
......@@ -132,4 +133,16 @@ public interface JavaLangAccess {
* Invokes the finalize method of the given object.
*/
void invokeFinalize(Object o) throws Throwable;
/**
* Set the value of {@code thread.resourceContainer}
*
* @param thread target thread to be modified
*/
void setResourceContainer(Thread thread, AbstractResourceContainer container);
/**
* Get the reference to the thread attached {@code ResourceContainer}
*/
AbstractResourceContainer getResourceContainer(Thread thread);
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/*
* @test
* @summary Test builder and update constraint
* @library /lib/testlibrary
* @run main TestConfiguration
*/
import demo.MyResourceContainer;
import demo.MyResourceFactory;
import demo.MyResourceType;
import java.util.Arrays;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static jdk.testlibrary.Asserts.assertTrue;
public class TestConfiguration {
public static void main(String[] args) {
MyResourceContainer mc = (MyResourceContainer) MyResourceFactory.INSTANCE.createContainer(Arrays.asList(
MyResourceType.MY_RESOURCE1.newConstraint(),
MyResourceType.MY_RESOURCE2.newConstraint()));
assertTrue(iterator2Stream(mc.operations.iterator()).collect(Collectors.toSet())
.equals(new HashSet<>(Arrays.asList("update MY_RESOURCE1", "update MY_RESOURCE2"))));
mc.updateConstraint(MyResourceType.MY_RESOURCE2.newConstraint());
assertTrue(iterator2Stream(mc.operations.iterator()).collect(Collectors.toSet())
.equals(new HashSet<>(Arrays.asList("update MY_RESOURCE1", "update MY_RESOURCE2", "update MY_RESOURCE2"))));
}
private static <T> Stream<T> iterator2Stream(Iterator<T> iterator) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED),
false);
}
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/*
* @test
* @summary Test resource container is inherited from parent
* @library /lib/testlibrary
* @run main TestInherit
*/
import com.alibaba.rcm.ResourceContainer;
import demo.MyResourceFactory;
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import static jdk.testlibrary.Asserts.assertEQ;
public class TestInherit {
public static void main(String[] args) {
assertEQ(ResourceContainer.current(), ResourceContainer.root());
ResourceContainer rc = MyResourceFactory.INSTANCE.createContainer(Collections.emptyList());
rc.run(() -> {
assertEQ(ResourceContainer.current(), rc);
FutureTask<ResourceContainer> f1 = new FutureTask<>(ResourceContainer::current);
new Thread(f1).start();
assertEQ(get(f1), rc);
FutureTask<ResourceContainer> f2 = new FutureTask<>(ResourceContainer::current);
ResourceContainer.root().run(() -> new Thread(f2).start());
assertEQ(get(f2), ResourceContainer.root());
});
// thread is bound to it's parent thread(the thread called Thread::init())
// not dependent on where Thread::start() called.
FutureTask<ResourceContainer> f3 = new FutureTask<>(ResourceContainer::current);
Thread t3 = new Thread(f3);
// Thread::init is called in root()
rc.run(t3::start);
assertEQ(get(f3), ResourceContainer.root());
FutureTask<ResourceContainer> f4 = new FutureTask<>(ResourceContainer::current);
FutureTask<Thread> newThread = new FutureTask<>(() -> new Thread(f4));
// Thread::init is called in container
rc.run(newThread);
get(newThread).start();
assertEQ(get(f4), rc);
}
private static <V> V get(Future<V> f) {
try {
return f.get();
} catch (InterruptedException | ExecutionException e) {
throw new InternalError(e);
}
}
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/*
* @test
* @summary Test skeletal implementation in AbstractResourceContainer
* @library /lib/testlibrary
* @run main TestSkeletalAttach
*/
import com.alibaba.rcm.ResourceContainer;
import demo.MyResourceContainer;
import demo.MyResourceFactory;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static jdk.testlibrary.Asserts.assertTrue;
public class TestSkeletalAttach {
public static void main(String[] args) {
MyResourceContainer rc = (MyResourceContainer) MyResourceFactory.INSTANCE.createContainer(Collections.emptyList());
rc.run(() -> {
assertListEQ(Collections.singletonList("attach"), rc.operations);
});
assertListEQ(Arrays.asList("attach", "detach"), rc.operations);
rc.operations.clear();
rc.run(() -> {
rc.run(() -> {
assertListEQ(Collections.singletonList("attach"), rc.operations);
});
});
assertListEQ(Arrays.asList("attach", "detach"), rc.operations);
rc.operations.clear();
rc.run(() -> {
assertListEQ(Collections.singletonList("attach"), rc.operations);
ResourceContainer.root().run(() -> {
assertListEQ(Arrays.asList("attach", "detach"), rc.operations);
});
});
assertTrue(Arrays.asList("attach", "detach", "attach", "detach").equals(rc.operations));
rc.operations.clear();
rc.run(() -> {
assertListEQ(Collections.singletonList("attach"), rc.operations);
ResourceContainer.root().run(() -> {
rc.run(() -> {
assertListEQ(Arrays.asList("attach", "detach", "attach"), rc.operations);
});
});
});
assertTrue(Arrays.asList("attach", "detach", "attach", "detach", "attach", "detach").equals(rc.operations));
}
private static void assertListEQ(List<String> lhs, List<String> rhs) {
assertTrue(lhs.equals(rhs), "expect " + lhs + " equals to " + rhs);
}
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/*
* @test
* @summary Test get tenant state
* @library /lib/testlibrary
* @run main TestState
*/
import com.alibaba.rcm.ResourceContainer;
import demo.MyResourceFactory;
import java.util.Collections;
import static jdk.testlibrary.Asserts.*;
public class TestState {
public static void main(String[] args) {
ResourceContainer rc = MyResourceFactory.INSTANCE.createContainer(Collections.emptyList());
assertEQ(rc.getState(), ResourceContainer.State.RUNNING);
rc.destroy();
assertEQ(rc.getState(), ResourceContainer.State.DEAD);
}
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/*
* @test
* @summary Test switch between containers
* @library /lib/testlibrary
* @run main TestSkeletalAttach
*/
import com.alibaba.rcm.ResourceContainer;
import demo.MyResourceFactory;
import java.util.Collections;
import static jdk.testlibrary.Asserts.*;
public class TestSwitchBetweenContainers {
public static void main(String[] args) {
ResourceContainer rc1 = MyResourceFactory.INSTANCE.createContainer(Collections.emptyList());
ResourceContainer rc2 = MyResourceFactory.INSTANCE.createContainer(Collections.emptyList());
boolean hasIllegalStateException = false;
try {
rc1.run(() -> {
rc2.run(() -> {
});
});
} catch (IllegalStateException e) {
hasIllegalStateException = true;
}
assertTrue(hasIllegalStateException);
rc1.run(() -> {
ResourceContainer.root().run(() -> {
rc2.run(() -> {
});
});
});
}
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package demo;
import com.alibaba.rcm.Constraint;
import com.alibaba.rcm.internal.AbstractResourceContainer;
import java.util.ArrayList;
import java.util.List;
public class MyResourceContainer extends AbstractResourceContainer {
public List<String> operations = new ArrayList<>();
private boolean dead;
@Override
protected void attach() {
super.attach();
operations.add("attach");
}
@Override
protected void detach() {
super.detach();
operations.add("detach");
}
@Override
public State getState() {
return dead ? State.DEAD : State.RUNNING;
}
@Override
public void updateConstraint(Constraint constraint) {
operations.add("update " + constraint.getResourceType());
}
@Override
public Iterable<Constraint> getConstraints() {
return null;
}
@Override
public void destroy() {
dead = true;
}
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package demo;
import com.alibaba.rcm.Constraint;
import com.alibaba.rcm.ResourceContainer;
import com.alibaba.rcm.ResourceContainerFactory;
public class MyResourceFactory implements ResourceContainerFactory {
public final static ResourceContainerFactory INSTANCE = new MyResourceFactory();
private MyResourceFactory() { /*pass*/}
@Override
public ResourceContainer createContainer(Iterable<Constraint> constraints) {
MyResourceContainer container = new MyResourceContainer();
for (Constraint constraint : constraints) {
container.updateConstraint(constraint);
}
return container;
}
}
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
package demo;
import com.alibaba.rcm.ResourceType;
public class MyResourceType extends ResourceType {
public final static ResourceType MY_RESOURCE1 = new MyResourceType("MY_RESOURCE1");
public final static ResourceType MY_RESOURCE2 = new MyResourceType("MY_RESOURCE2");
public MyResourceType(String name) {
super(name);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册