Monitor
class represents a monitor attached to a Simulator
instance. Created by the MonitorFactory
class, a monitor collects statistics about a program as it runs, and then when the simulation is complete, generates a report.
@author Ben L. Titzer
{@code}if (monitor.tryEnter()) try { // do things while occupying the monitor } finally { monitor.leave(); } } else { // do other things since the monitor was not available }}
The following examples show a simple threadsafe holder expressed using {@code synchronized}, {@link ReentrantLock}, and {@code Monitor}.
This version is the fewest lines of code, largely because the synchronization mechanism used is built into the language and runtime. But the programmer has to remember to avoid a couple of common bugs: The {@code wait()} must be inside a {@code while} instead of an {@code if}, and {@code notifyAll()} must be used instead of {@code notify()} because there are two differentlogical conditions being awaited.
{@code}public class SafeBoxprivate V value; public synchronized V get() throws InterruptedException { while (value == null) { wait(); } V result = value; value = null; notifyAll(); return result; } public synchronized void set(V newValue) throws InterruptedException { while (value != null) { wait(); } value = newValue; notifyAll(); } }}
This version is much more verbose than the {@code synchronized} version, and still suffersfrom the need for the programmer to remember to use {@code while} instead of {@code if}. However, one advantage is that we can introduce two separate {@code Condition} objects, whichallows us to use {@code signal()} instead of {@code signalAll()}, which may be a performance benefit.
{@code}public class SafeBoxprivate final ReentrantLock lock = new ReentrantLock(); private final Condition valuePresent = lock.newCondition(); private final Condition valueAbsent = lock.newCondition(); private V value; public V get() throws InterruptedException { lock.lock(); try { while (value == null) { valuePresent.await(); } V result = value; value = null; valueAbsent.signal(); return result; } finally { lock.unlock(); } } public void set(V newValue) throws InterruptedException { lock.lock(); try { while (value != null) { valueAbsent.await(); } value = newValue; valuePresent.signal(); } finally { lock.unlock(); } } }}
This version adds some verbosity around the {@code Guard} objects, but removes that sameverbosity, and more, from the {@code get} and {@code set} methods. {@code Monitor} implements thesame efficient signaling as we had to hand-code in the {@code ReentrantLock} version above.Finally, the programmer no longer has to hand-code the wait loop, and therefore doesn't have to remember to use {@code while} instead of {@code if}.
{@code}public class SafeBox@author Justin T. Sampson @since Guava release 10private final Monitor monitor = new Monitor(); private final Monitor.Guard valuePresent = new Monitor.Guard(monitor) { public boolean isSatisfied() { return value != null; } }; private final Monitor.Guard valueAbsent = new Monitor.Guard(monitor) { public boolean isSatisfied() { return value == null; } }; private V value; public V get() throws InterruptedException { monitor.enterWhen(valuePresent); try { V result = value; value = null; return result; } finally { monitor.leave(); } } public void set(V newValue) throws InterruptedException { monitor.enterWhen(valueAbsent); try { value = newValue; } finally { monitor.leave(); } } }}
Also, the {@link #sendEvent(Event)} allows a Mondrian subsystem tonotify the monitor of some event. The event is handled asynchronously. We strongly recommend that the event's fields simple, final values; one would not want the contents to have changed when the event is processed, or for the event to prevent a resource from being garbage-collected.
All methods are thread-safe.
Services
A service is a collection of modules that combine to provide the full functionality defined by the service. A service is defined by three pieces of information:
Booting Services
Services can be booted a number of ways
derby.service.service name=class name e.g. # Added to the properties automatically by the class org.apache.derby.jdbc.EmbeddedDriver derby.service.jdbc=java.sql.Driver
derby.service.service name=persistent storage type e.g. derby.service.mydatabase=serviceDirectoryserviceDirectory is a type understood by the monitor which means that there is a directory named mydatabase within the system directory and within it is a properties file service.properties. This properties set is the set for the service and must contain a property
derby.protocol=class nameThis is then the factory interface for the service. Other storage types could be added in the future.
System Service
A special service exists, the System Service. This service has no factory interface, no identifier and no Properties set. It allows modules to be started that are required by another service (or the monitor itself) but are not fundamentally part of the service. Modules within this service are unidentified. Typically these modules are system wide types of functionality like streams, uuid creation etc.
The lifetime of a system module is the lifetime of the monitor. Optionally - this could be changed to reference count on individual modules, requires some minor api changes.
Modules
A module is found or booted using four pieces of information:
Module Implementations
When creating an instance of a module, an implementation is found through lists of potential implementations.
A list of potential implementations is obtained from a Properties set. Any property within this set that is of the form
derby.module.tag=java class nameis seen by the monitor as a possible implementation. tag has no meaning within the monitor, it is only there to provide uniqueness within the properties file. Typically the tag is to provide some description for human readers of the properties file, e.g. derby.module.lockManager for an implementation of a lock manager.
Module Searching
When searching for a module the search space is always restricted to a single service. This service is usually the system service or the service of the module making the search request. It would be very rare (wrong?) to search for a module in a service that was not the current service and not the system service.
Within the list of modules in the service the search is conducted as follows:
Service Properties
Within the service's Properties a module may search for its parameters. It identifies its parameters using a unqiue parameter name and its identifier.
Unique parameter names are made unique through the 'dot' convention of Properties files. A module protocol picks some unique key portion to start, e.g. RawStore for the RawStoreFactory and then extends that for specific parameters, e.g. RawStore.PageSize. Thus parameters that are typically understood by all implementations of that protocol would start with that key portion. Parameters for specific implementations add another key portion onto the protocol key portion, e.g. RawStore.FileSystem for an file system implementation of the raw store, with a specific parameter being RawStore.FileSystem.SectorSize.
These are general guidelines, UUID's could be used as the properties keys but would make the parameters hard to read.
When a module is unidentified it should look for a parameter using just the property key for that parameter, e.g. getProperty("RawStore.PageSize").
When a module has an identifier is should look for a property using the key with a dot and the identifier appended, e.g. getProperty("RawStore.PageSize" + "." + identifier).
In addition to searching for parameters in the service properties set, the system and application set may be searched using the getProperty() method of ModuleFactory.
Should any order be defined for this, should it be automatic?
For each request submitted to a GeoServer instance the monitor maintains state about the request and makes operations available that control the life cycle of the request. The life cycle of a monitored request advances through the following states:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|