Resource Management

This document discusses the basic principles of resource management in the mBS framework.

Contents:


Overview

In a system which lacks sufficient resources, a proper management must distribute or limit the usage of the available resources among the parties in the system, due to some priority. For example, when a bundle has allocated too much memory, thus threatening the work of the rest of the components in the framework, then it must either be stopped, or - if there is a way - to prevent more memory allocation.

Different embedded systems (hardware and OS) may lack different kind of system resources: operational memory, persistent memory, threads, sockets, etc. Different VMs offer VM-specific approaches to management of such system resources, for example J9 allows management of operational memory, Jbed provides means for monitoring and management of CPU-time usage, conventional JDK1.1 allows control over thread creation. The framework provides an interface, which unites all VM-dependent resource managers.

Note: On Tao or Skelmir VM, the mbs.threads.fix system property must be set to true in order to use some VM-specific techniques for resource management.

Resource Manager

Based on bundle's resource requirements and framework default values for those resources, a resource manager monitors each bundle's allocations, and when they reach undesired limits it may either refuse to give any more resources or to stop the bundle.

Resource Manager Service

The active resource manager is available as a System Bundle service in the framework. You can use it to monitor current bundle resource allocations and to switch between resource contexts of bundles.

Available Resource Managers

mBS offers two resource manager implementations:

Switching On and Off Resource Management

Resource management is activated with the mbs.resman.enabled system property. The resource manager implementation class is set as value to the system property mbs.resman.class, so that the framework can instantiate the proper resource manager for the current VM.

Declaration of Bundle Resource Requirements

A bundle can declare requirements for system resources, so that it is clear how much memory, sockets, etc. it needs. During development, bundle needs of resources are analyzed and the results are incorporated in the bundle JAR. For example after passing some overloading tests, it becomes evident that the greatest portion of memory that a bundle can take is 100KB. This is put as a resource requirement in the bundle. So, if this bundle exceeds 100Kbytes memory allocation, this implies that something wrong has happened with bundle's normal operation. The framework (in this case presented by a resource manager) gives the bundle no more than the requested resources or the default maximum - whichever is less. This is a precaution in case a bundle allocates more resources than it normally does - this means that it functions improperly - and the resource manager must take some response actions to repair the bundle and/or to stop the process of resource allocation.

Rarely, there are resources, which two different VMs can manage at the same time. Hence, managed resources are separated by VMs in their description.

The resource requirements of a bundle are specified in a requirement XML. The listing below illustrates how needed resources should be specified in an XML:

  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE Resources SYSTEM "res.dtd">
  <BundleRequirements>
<Resources>
<VM>
<Resource>
<Name>DataStorageSpace</Name>
<Requirement>10240</Requirement>
</Resource>
<Resource>
<Name>BundleThreads</Name>
<Requirement>5</Requirement>
</Resource>
</VM> <VM name="J9"> <Resource> <Name>BundleSockets</Name> <Requirement>5</Requirement> </Resource> </VM> </Resources>
. . .
</
BundleRequirments>
Listing 1: An example resource requirement XML.

The XML in Listing 1 describes some resource requirements for J9 and any VM.

Tip: The "Managed Resources" section describes the resource names to fill in the requirement XML.

Resource Context

Resource context is an abstraction for the context in which a bundle requests and uses resources. The resource manager assigns each bundle a separate resource context.

The resource manager uses the resource context abstraction to track the resources consumed by each bundle. When a request for a resource is received, the resource manager checks the resource context associated with the bundle. If the bundle owning this resource context is not allowed to get (any more) instances of this resource type, an exception is thrown.

Switching Issues

Bundles are able to switch between different resource contexts. When a bundle calls a method of an object belonging to another bundle, it is recommended that the bundle switches to the resource context of the target object. This is specially necessary if the method is going to consume some resources. By default, switching to the resource context of the System Bundle (in other words of the framework) is not allowed.

Another switching issue is that of making a method end in the same context in which it starts.

A resource context is created just before a bundle activator is instantiated. The framework resource manager guarantees that a bundle resource context is switched on just before invoking the following methods:

When a class is loaded by the bundle that owns it (the class is found in the bundle JAR), it is loaded in the resource context belonging to this bundle. In this way, the class static fields are loaded in the bundle resource context, not in the framework one.

The class loaders for all bundles are stored within the framework resource context.

When a bundle is uninstalled, the framework switches all referent resources to an empty resource context, which belongs to no entity. Thus, all entities that have switched to resource context of the bundle and are currently using its resources, are redirected to the empty context.

Managed Resources

Active Threads

Overview

If a bundle creates too many threads or any of them consumes too much system resources, the bundle can be easily identified and sanctioned.

Switching the resource context of a thread does not assign the thread to the bundle owning the new resource context in terms of changing the count of the bundle’s active threads. Switching of the resource context has effect only on the newly requested resources by the corresponding thread.

Tip: By using the Thread Pool Manager service for short-living thread you can avoid the restrictions imposed on the number of active threads a bundle can have. In this case, the thread number is restricted by the Thread Pool Manager itself through its system properties.

Specifying Required Threads

A bundle indicates how many active threads it needs in its requirement XML by including the BundleThreads resource name.

Settings

If there is no information about the threads a bundle requires, the values of the mbs.resman.DefBundleThreads, mbs.resman.MaxBundleThreads and mbs.resman.maxThreads system properties are used.

Data Storage Space

Overview

The data storage space resource is the data space allocation per bundle.

Monitoring over the data storage space for every bundle is done by the storage implementation used in the Connector Version of the framework. On detecting that a bundle has reached its storage space limit, the storage module throws a java.io.EOFException to any write operation on a file in the bundle data directory. In this way the bundle is informed that it should free some space by shrinking its data. The Default Resource Manager only parses bundle data space requirements.

For the Standard Version of the framework and for J9 v2.x, the Default Resource Manager itself cares for limiting the data space of bundles.

Specifying Required Data Space

The data space that a bundle requires can be declared in a bundle requirement XML under the DataStorageSpace resource name.

Settings

If there is no requirement XML or the requirement for the data space is missing, then the values of the mbs.resman.DefDataStorageSpace and mbs.resman.MaxDataStorageSpace system properties are taken.

J9 Specific Resources

There is a special resource manager designed for J9 2.x, which handles memory spaces and bundle sockets.

Memory Spaces Support

On the J9 VM, the mBS framework supports allocation of memory spaces for each bundle. Memory spaces are introduced by the IBM Corporation and are included in the WebSphere Studio Device Developer (WSDD).

Overview. The concept of memory spaces concentrates around segmenting the available memory and allocating a separate piece of it for every running thread. This facilitates resource management and memory constraints. It also prevents flawed or unauthorized applications to intrude into the memory allocated for a module. For more information about the advantages and usage of memory spaces, refer to the WSDD documentation.

Specifying required memory space. A bundle may specify a requirement for the memory space that will be allocated for it at startup. This requirement should specified in the requirement XML file (see above) with the NewSegmentSize and OldSegmentSize within the <VM name="J9"> tag.

Settings. If the bundle requirement XML is not found, or it contains illegal or corrupted information, memory space resource requirements are constructed using the memory space system properties: mbs.resman.j9.newspacesize, mbs.resman.j9.oldspacesize and mbs.resman.j9.maxspacesize.

Switching between memory spaces. Memory spaces are switched in a transparent way by using bundle resource contexts - by switching between resource contexts you switch between memory spaces.

Troubleshooting. When memory spaces are created for bundles, which are not designed to work in such an environment, then it may happen that a memory space is quickly filled up and an OutOfMemoryError is thrown. It may occur to receive OutOfMemoryError during normal work on the framework - the reason is that our bundles are not enabled for memory spaces. The bundles do not switch the memory space when they invoke another bundles code, so objects are created in the memory space of the calling thread whatever it happens to be.

In order to guarantee normal work on a framework with memory spaces, all bundles (or at least those which rent services and resources) should implement switching logic using the Resource Manager service in the framework.

Bundle Sockets

The J9 Resource Manager can limit the total number of sockets open by all bundles and the framework.

Specifying required bundle sockets. A bundle can specify the number of sockets it requires in its requirement XML using the BundleSockets resource name within the <VM name="J9"> tag.

Settings. If a bundle has no requirement XML or this XML does not contain information about required sockets, then the values of the mbs.resman.DefBundleSockets, mbs.resman.MaxBundleSockets, and mbs.resman.maxSockets system properties are used.

Monitoring Resource Consumption

Used resources in the framework can be viewed through the Resource Manager service of the System Bundle, from framework text console (local and Telnet) and from the mConsole.

The framework text console provides the info.resman command. In addition, when the J9 Resource Manager is used, you can inspect the memory spaces of bundles with the info.memory command.

The mConsole shows the resource requirements and allocations of each bundle. Also you can load a diagram for all bundles' allocations, so that a comparison between bundles can be made.

Custom Resource Manager

You can provide a custom resource manager. It must extend the com.prosyst.mbs.impl.framework.module.resman.AbstractResourceManager public class, which implements the com.prosyst.mbs.framework.resman.ResourceManager interface. Then, you should manifest the implementation class with the mbs.resman.class system property.

Following is a brief description of the methods of com.prosyst.mbs.impl.framework.module.resman.AbstractResourceManager that should be overridden by a custom resource manager:

Public Method Description
void checkThreadCreation(ThreadGroup group) Checks if the creation of a new thread is allowed. For example, it can be checked if the bundle has exceeded the allowed limit of active threads. If this is true, the resource manager should block the creation of the new thread.
void cleanAll() Cleans unused objects thus easing the work of the framework. The framework calls this method when necessary.
String switchToBundleContext(Bundle bundle, boolean allowSysSwitch) Switches to the resource context of the specified bundle. The allowSysSwitch flag indicates if switching to the System Bundle context is allowed.
String switchToContext(String ctx) Switches to the context with the specified name. If the target context name is equal to the System Bundle context, then this switching is not allowed.
String switchToObjectContext(java.lang.Object o, boolean allowSysSwitch) Switches to the resource context of the specified object. The allowSysSwitch flag shows if switching to the System Bundle context is allowed.
void switchToNewContext(Bundle bundle) Creates a new context for the specified bundle and sets it as current.
void removeContext(Bundle bundle) Removes the context of the specified bundle. In general, this method may mark the context as invalid and forbid switching to it.

The methods defined by the ResourceManager interface can be also extended or overridden - see the API documentation for more details about them. In addition, the following public methods and fields are provided in AbstractResourceManager:

ExternalizableDictionary
getResourceRequirements(Bundle bundle)
Returns the bundle requirements for the default VM, J9 and Jbed, specified in the bundle requirement XML. Initially, these are required active threads and data storage space.
static String EMPTY_CONTEXT = "EmptyContext" Represents an empty resource context of a bundle.
void switchToEmptyContext(String context) Switches to the resource context with the specified name. On failure the method switches to the empty resource context - that is to EMPTY_CONTEXT.

References


Framework Architecture