Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Misc] Resource Management API #8

Merged
merged 1 commit into from
Mar 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion make/CreateJars.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
85 changes: 85 additions & 0 deletions src/share/classes/com/alibaba/rcm/Constraint.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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) +
'}';
}
}
210 changes: 210 additions & 0 deletions src/share/classes/com/alibaba/rcm/ResourceContainer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/*
* 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();
}
60 changes: 60 additions & 0 deletions src/share/classes/com/alibaba/rcm/ResourceContainerFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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);
}
Loading