mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2024-11-24 09:40:30 -06:00
docs update
This commit is contained in:
parent
da609d76da
commit
ac78ea5667
@ -2,13 +2,13 @@ package io.nosqlbench.adapter.prototype;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) nosqlbench
|
* Copyright (c) nosqlbench
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing,
|
* Unless required by applicable law or agreed to in writing,
|
||||||
* software distributed under the License is distributed on an
|
* software distributed under the License is distributed on an
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
@ -21,6 +21,9 @@ package io.nosqlbench.adapter.prototype;
|
|||||||
import io.nosqlbench.adapters.api.activityimpl.uniform.BaseSpace;
|
import io.nosqlbench.adapters.api.activityimpl.uniform.BaseSpace;
|
||||||
import io.nosqlbench.adapters.api.activityimpl.uniform.DriverAdapter;
|
import io.nosqlbench.adapters.api.activityimpl.uniform.DriverAdapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public class ExampleSpace extends BaseSpace<ExampleSpace> {
|
public class ExampleSpace extends BaseSpace<ExampleSpace> {
|
||||||
|
|
||||||
public ExampleSpace(DriverAdapter<?, ExampleSpace> adapter, long idx) {
|
public ExampleSpace(DriverAdapter<?, ExampleSpace> adapter, long idx) {
|
||||||
|
@ -23,6 +23,9 @@ import io.nosqlbench.adapters.api.activityimpl.uniform.flowtypes.CycleOp;
|
|||||||
/**
|
/**
|
||||||
* This example of a space uses the <EM>SelfT</EM> technique to enable
|
* This example of a space uses the <EM>SelfT</EM> technique to enable
|
||||||
* the self type to be used in method signatures and return types.
|
* the self type to be used in method signatures and return types.
|
||||||
|
*
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
* @param <SelfT>
|
* @param <SelfT>
|
||||||
*/
|
*/
|
||||||
public class BaseSpace<SelfT extends BaseSpace<SelfT> > implements Space {
|
public class BaseSpace<SelfT extends BaseSpace<SelfT> > implements Space {
|
||||||
|
@ -35,120 +35,114 @@ import java.util.Optional;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.LongFunction;
|
import java.util.function.LongFunction;
|
||||||
|
|
||||||
/**
|
|
||||||
* <P>The DriverAdapter interface is the top level API for implementing
|
/// The DriverAdapter interface is the top level API for implementing
|
||||||
* operations in NoSQLBench. It defines the related APIs needed to fully realized an adapter
|
/// operations in NoSQLBench. It defines the related APIs needed to fully realized an adapter
|
||||||
* at runtime. A driver adapter can map op templates from YAML form to a fully executable
|
/// at runtime. A driver adapter can map op templates from YAML form to a fully executable
|
||||||
* form in native Java code, just as an application might do with a native driver. It can also
|
/// form in native Java code, and then execute those native operations just as an application might do directly with a
|
||||||
* do trivial operations, like simply calling {@code System.out.println(...)}. When you specify an adapter by name,
|
/// native driver. It can also do trivial operations, like simply calling `System.out.println(...)`. What a
|
||||||
* you are choosing both the available operations, and the rules for converting a YAML op template into those
|
/// particular DriverAdapter does is open-ended, but this usually means wrapping a native driver when supporting
|
||||||
* operations. This is a two-step process: The adapter provides mapping logic for converting high-level templates from
|
/// specific protocols.
|
||||||
* users into op types, and separate dispensing logic which can efficiently create these ops at runtime. When used
|
///
|
||||||
* together, they power <EM>op synthesis</EM> -- efficient and deterministic construction of runtime operations using
|
/// Every DriverAdapter has a simple name, as indicated on it's [Service] annotation. When you
|
||||||
* procedural generation methods.
|
/// specify an adapter by name, you are choosing both the available operations, and the rules for converting
|
||||||
* </p>
|
/// a YAML op template into those operations. This is a two-step process: Mapping user intentions, and generating
|
||||||
*
|
/// executable operations, called op mapping and op dispensing, respectively. Each adapter provides implementations
|
||||||
* <p>
|
/// for both of these phases for all the op types is supports. When used together, they power _op synthesis_ --
|
||||||
* Generally speaking, a driver adapter is responsible for
|
/// efficient and deterministic construction of runtime operations using procedural generation methods.
|
||||||
* <UL>
|
///
|
||||||
* <LI>Defining a class type for holding related state known as a {@link Space}.
|
/// Generally speaking, a driver adapter is responsible for
|
||||||
* <UL><LI>The type of this is specified as
|
/// - Defining a class type for holding related state known as a [Space]. The type of this is specified as generic
|
||||||
* generic parameter {@link SPACETYPE}.</LI></UL></LI>
|
/// parameter [SPACETYPE]
|
||||||
* <LI>Defining a factory method for constructing an instance of the space.</LI>
|
/// - Defining a factory method for constructing an instance of the space.
|
||||||
* <LI>Recognizing the op templates that are documented for it via an {@link OpMapper}
|
/// - Recognizing the op templates that are documented for it via an [OpMapper] and assigning them to an op
|
||||||
* and assigning them to an op implementation.
|
/// implementation. The base type of these ops is specified as generic [OPTYPE]
|
||||||
* <UL><LI>The base type of these ops is specified as generic
|
/// - Constructing dispensers for each matching op implementation with a matching [OpDispenser] implementation.
|
||||||
* parameter {@link OPTYPE}.</LI></UL>
|
///
|
||||||
* </LI>
|
/// At a high level, the following sequence is executed for every cycle in an activity:
|
||||||
* <LI>Constructing dispensers for each matching op implementation with a matching {@link OpDispenser}</LI>
|
/// ```
|
||||||
* implementation.
|
///[cycle value] -> op synthesis -> [executable op] -> op execution```
|
||||||
* </UL>
|
///
|
||||||
* <P>At runtime, the chain of these together ({@code cycle -> op mapping -> op dispensing -> op}) is cached
|
/// or in another way, simply `opExecution(opFunction(cycle))`.
|
||||||
* as a look-up table of op dispensers. This results in the simpler logical form {@code cycle -> op synthesis ->
|
///
|
||||||
* operation}.
|
/// This is a simplified view of the detailed steps, most of which are handled automatically by the nosqlbench engine:
|
||||||
* </P>
|
///
|
||||||
*
|
/// ```
|
||||||
* <H3>Variable Naming Conventions</H3>
|
/// cycle value
|
||||||
* <p>
|
/// -> op template sequencing # memoized
|
||||||
* Within the related {@link DriverAdapter} APIs, the following conventions are (more often) used, and will be found
|
/// -> op template selection # memoized
|
||||||
* everywhere:
|
/// -> op template parsing # memoized
|
||||||
* <UL>
|
/// -> op template normalization # memoized
|
||||||
* <LI>{@code namedF} describes a namedFunction variable. Functional patterns are used everywhere in these APIs
|
/// -> op type mapping # memoized
|
||||||
* .</LI>
|
/// -> op dispensing
|
||||||
* <LI>{@code namedC} describes a namedComponent variable. All key elements of the nosqlbench runtime are
|
/// -> op execution
|
||||||
* part of a component tree.</LI>
|
///```
|
||||||
* <LI>{@code pop} describes a {@link ParsedOp} instance.</LI>
|
///
|
||||||
* </UL>
|
/// Notice that all of the stages are optimized via a form of memoization. This is a side-effect of forcing the
|
||||||
* </P>
|
/// initialization of the op construction pipelines into lamda form, where unchanging initialization data is captured
|
||||||
* <H3>Generic Parameters</H3>
|
/// explicitly or by reference in closures. This works in our favor for performance, since these lambdas are
|
||||||
* <p>
|
/// optimized and executed very efficiently within modern Java VMs.
|
||||||
* When a new driver adapter is defined with the generic parameters below, it becomes easy to build out a matching
|
///
|
||||||
* DriverAdapter with any modern IDE.</P>
|
/// ### Variable Naming Conventions
|
||||||
*
|
///
|
||||||
* @param <OPTYPE>
|
/// Within the related [DriverAdapter] APIs, the following conventions are (more often) used, and will be
|
||||||
* The type of {@link CycleOp} which will be used to wrap all operations for this driver adapter. This allows you
|
/// found everywhere:
|
||||||
* to add context or features common to all operations of this type. This can be a simple <a
|
/// - `namedF` describes a namedFunction variable. Functional patterns are used everywhere in these APIs.
|
||||||
* href="https://en.wikipedia.org/wiki/Marker_interface_pattern">Marker</a> interface, or it can be something more
|
/// - `namedC` describes a namedComponent variable. All key elements of the nosqlbench runtime are part of a
|
||||||
* concrete that captures common logic or state across all the operations used for a given adapter. It is highly
|
/// component tree.
|
||||||
* advised to <EM>NOT</EM> leave it as simply {@code CycleOp<?>}, since specific op implementations offer much
|
/// - `pop` describes a [ParsedOp] instance.
|
||||||
* better performance.
|
///
|
||||||
* @param <SPACETYPE>
|
/// ### Generic Parameters
|
||||||
* The type of context space used by this driver to hold cached instances of clients, session, or other native
|
/// When a new driver adapter is defined with the generic parameters below, it becomes easy to build out a matching
|
||||||
* driver state. This is the shared state which might be needed during construction operations for an adapter.
|
/// [DriverAdapter] with any modern IDE.
|
||||||
* <EM>No other mechanism is provided nor intended for holding adapter-specific state. You must store it in
|
///
|
||||||
* this type. This includes client instances, codec mappings, or anything else that a single instance of an
|
/// @param OPTYPE The type of [CycleOp] which will be used to wrap all operations for this driver adapter. This
|
||||||
* application would need to effectively use a given native driver.</EM>
|
/// allows you to add context or features common to all operations of this type. This can be a simple
|
||||||
*/
|
/// [marker](https://en.wikipedia.org/wiki/Marker_interface_pattern) interface, or it can be something more concrete
|
||||||
|
/// that captures common logic or state across all the operations used for a given adapter. It is
|
||||||
|
/// highly advised to _NOT_ leave it as simply `CycleOp<?>`, since specific op implementations offer much
|
||||||
|
/// better performance.
|
||||||
|
///
|
||||||
|
/// @param SPACETYPE The type of context space used by this driver to hold cached instances of clients, session, or
|
||||||
|
/// other native driver state. This is the shared state which might be needed during construction operations for an
|
||||||
|
/// adapter. No other mechanism is provided nor intended for holding adapter-specific state. You must store it in
|
||||||
|
/// this type. This includes client instances, codec mappings, or anything else that a single instance of an
|
||||||
|
/// application would need to effectively use a given native driver.
|
||||||
public interface DriverAdapter<OPTYPE extends CycleOp<?>, SPACETYPE extends Space> extends NBComponent {
|
public interface DriverAdapter<OPTYPE extends CycleOp<?>, SPACETYPE extends Space> extends NBComponent {
|
||||||
|
|
||||||
/**
|
///
|
||||||
* <p>
|
/// ## Op Mapping
|
||||||
* <H2>Op Mapping</H2>
|
///
|
||||||
* An Op Mapper is a function which can look at a {@link ParsedOp} and create a matching {@link OpDispenser}.
|
/// An Op Mapper is a function which can look at a [ParsedOp] and create a matching [OpDispenser].
|
||||||
* An OpDispenser is a function that will produce a special type {@link OPTYPE} that this DriverAdapter implements
|
/// An OpDispenser is a function that will produce a special type [OPTYPE] that this DriverAdapter implements.
|
||||||
* as its op implementation. There may be many different ops supported by an adapter, thus there may be similarly
|
/// There may be many different ops supported by an adapter, thus there may be similarly many dispensers.
|
||||||
* many dispensers.</p>
|
///
|
||||||
*
|
/// Both [OpMapper] and [OpDispenser] are functions. The role of [OpMapper] is to map the op template provided
|
||||||
* <p>
|
/// by the user to an op implementation provided by the driver adapter, and then to create a suitable function for
|
||||||
* Both {@link OpMapper} and {@link OpDispenser} are functions. The role of {@link OpMapper} is to
|
/// creating that type of operations, known as the [OpDispenser].
|
||||||
* map the op template provided by the user to an op implementation provided by the driver adapter,
|
///
|
||||||
* and then to create a factor function for it (the {@link OpDispenser}).</p>
|
/// These roles are split for a very good reason: Mapping what the user wants to do with an op template
|
||||||
*
|
/// is resource intensive, and should be as pre-baked as possible. This phase is the _op mapping_ phase.
|
||||||
* <p>These roles are split for a very good reason: Mapping what the user wants to do with an op template
|
/// It is essential that the mapping logic be very clear and maintainable. Performance is not as important
|
||||||
* is resource intenstive, and should be as pre-baked as possible. This phase is the <EM>op mapping</EM> phase.
|
/// at this phase, because all of the mapping logic is run during initialization of an activity.
|
||||||
* It is essential that the mapping logic be very clear and maintainable. Performance is not as important
|
///
|
||||||
* at this phase, because all of the mapping logic is run during initialization of an activity.
|
/// Conversely, _op dispensing_ (the next phase) while an activity is running should be as efficient as possible.
|
||||||
* </p>
|
/// @return a dispensing function for an [OPTYPE] op generation
|
||||||
* <p>
|
|
||||||
* Conversely, <EM>op dispensing</EM> (the next phase) while an activity is running should be as efficient as
|
|
||||||
* possible.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a dispensing function for {@link OPTYPE} op generation
|
|
||||||
*/
|
|
||||||
OpMapper<OPTYPE, SPACETYPE> getOpMapper();
|
OpMapper<OPTYPE, SPACETYPE> getOpMapper();
|
||||||
|
|
||||||
/**
|
/// The preprocessor function allows the driver adapter to remap the fields in the op template before they are
|
||||||
* The preprocessor function allows the driver adapter to remap
|
/// interpreted canonically. At this level, the transform is applied once to the input map (once per op
|
||||||
* the fields in the op template before they are interpreted canonically.
|
/// template) to yield the map that is provided to [OpMapper] implementations. _This is here to make
|
||||||
* At this level, the transform is applied once to the input map
|
/// backwards compatibility possible for op templates which have changed. Avoid using it unless necessary._
|
||||||
* (once per op template) to yield the map that is provided to
|
/// @return A function to pre-process the op template fields.
|
||||||
* {@link OpMapper} implementations. <EM>This is here to make backwards compatibility
|
|
||||||
* possible for op templates which have changed. Avoid using it unless necessary.</EM>
|
|
||||||
*
|
|
||||||
* @return A function to pre-process the op template fields.
|
|
||||||
*/
|
|
||||||
default Function<Map<String, Object>, Map<String, Object>> getPreprocessor() {
|
default Function<Map<String, Object>, Map<String, Object>> getPreprocessor() {
|
||||||
return f -> f;
|
return f -> f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* When a driver needs to identify an error uniquely for the purposes of
|
/// When a driver needs to identify an error uniquely for the purposes of routing it to the correct error
|
||||||
* routing it to the correct error handler, or naming it in logs, or naming
|
/// handler, or naming it in logs, or naming metrics, override this method in your activity.
|
||||||
* metrics, override this method in your activity.
|
/// @return A function that can reliably and safely map an instance of Throwable to a stable adapter-specific name.
|
||||||
*
|
|
||||||
* @return A function that can reliably and safely map an instance of Throwable to a stable adapter-specific name.
|
|
||||||
*/
|
|
||||||
default Function<Throwable, String> getErrorNameMapper() {
|
default Function<Throwable, String> getErrorNameMapper() {
|
||||||
return t -> t.getClass().getSimpleName();
|
return t -> t.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
@ -157,20 +151,17 @@ public interface DriverAdapter<OPTYPE extends CycleOp<?>, SPACETYPE extends Spac
|
|||||||
return List.of(f -> f);
|
return List.of(f -> f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// This method allows each driver adapter to create named state which is automatically cached and re-used by
|
||||||
* <P>This method allows each driver adapter to create named state which is automatically
|
/// name. For each (driver,space) combination in an activity, a distinct space instance will be created. In
|
||||||
* cached and re-used by name. For each (driver,space) combination in an activity,
|
/// general, adapter developers will use the space type associated with an adapter to wrap native driver
|
||||||
* a distinct space instance will be created. In general, adapter developers will
|
/// instances one-to-one. As such, if the space implementation is an [AutoCloseable], it will be
|
||||||
* use the space type associated with an adapter to wrap native driver instances
|
/// explicitly shutdown as part of the activity shutdown.
|
||||||
* one-to-one. As such, if the space implementation is a {@link AutoCloseable},
|
///
|
||||||
* it will be explicitly shutdown as part of the activity shutdown.</P>
|
/// It is not necessary to implement a space for a stateless driver adapter, or one which injects all necessary
|
||||||
*
|
/// state into each op instance.
|
||||||
* <p>It is not necessary to implement a space for a stateless driver adapter, or one
|
///
|
||||||
* which puts all state into each op instance.</p>
|
/// @return A function which can initialize a new Space, which is a place to hold object state related to
|
||||||
*
|
/// retained objects for the lifetime of a native driver.
|
||||||
* @return A function which can initialize a new Space, which is a place to hold
|
|
||||||
* object state related to retained objects for the lifetime of a native driver.
|
|
||||||
*/
|
|
||||||
default LongFunction<SPACETYPE> getSpaceInitializer(NBConfiguration cfg) {
|
default LongFunction<SPACETYPE> getSpaceInitializer(NBConfiguration cfg) {
|
||||||
return n -> (SPACETYPE) new Space() {
|
return n -> (SPACETYPE) new Space() {
|
||||||
@Override
|
@Override
|
||||||
@ -180,38 +171,38 @@ public interface DriverAdapter<OPTYPE extends CycleOp<?>, SPACETYPE extends Spac
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provides the configuration for this driver adapter, which comes from the superset of
|
||||||
|
/// activity parameters given for the owning activity. Presently, the driver adapter acts
|
||||||
|
/// as a proxy to set these parameters on the space, but this will likely be updated.
|
||||||
|
/// Instead, the configuratin will be properly attached to the space directly, and the APIs
|
||||||
|
/// supporting it will enforce this.
|
||||||
NBConfiguration getConfiguration();
|
NBConfiguration getConfiguration();
|
||||||
|
|
||||||
/**
|
/// The standard way to provide docs for a driver adapter is to put them in one of two common places:
|
||||||
* The standard way to provide docs for a driver adapter is to put them in one of two common places:
|
/// - `resources/<adaptername>.md`
|
||||||
* <ul>
|
/// - A single markdown file which is the named top-level markdown file for this driver adapter.
|
||||||
* <li><resources>/<adaptername>.md - A single markdown file which is the named top-level
|
/// - `resources/docs/<adaptername>/`
|
||||||
* markdown file for this driver adapter.</li>
|
/// - A directory containing any type of file which is to be included in docs under the adapter name, otherwise
|
||||||
* <li><resources>/docs/<adaptername>/ - A directory containing any type of file which
|
/// known as the [Service#selector()]
|
||||||
* is to be included in docs under the adapter name, otherwise known as the {@link Service#selector()}</li>
|
/// - `resources/docs/<adaptername>.md`
|
||||||
* <li><resources>/docs/<adaptername>.md</li>
|
/// - An alternate location for the main doc file for an adapter, assuming you are using the docs/ path.
|
||||||
* </ul>
|
///
|
||||||
*
|
/// _A build will fail if any driver adapter implementation is missing at least one self-named markdown doc file._
|
||||||
* <P><EM>A build will fail if any driver adapter implementation is missing at least one self-named
|
///
|
||||||
* markdown doc file.</EM></P>
|
/// @return A [DocsBinder] which describes docs to include for a given adapter.
|
||||||
*
|
|
||||||
* @return A {@link DocsBinder} which describes docs to include for a given adapter.
|
|
||||||
*/
|
|
||||||
default DocsBinder getBundledDocs() {
|
default DocsBinder getBundledDocs() {
|
||||||
Docs docs = new Docs().namespace("drivers");
|
Docs docs = new Docs().namespace("drivers");
|
||||||
|
|
||||||
String dev_docspath = "adapter-" + this.getAdapterName() + "/src/main/resources/docs/" + this.getAdapterName();
|
String dev_docspath = "adapter-" + this.getAdapterName() + "/src/main/resources/docs/" + this.getAdapterName();
|
||||||
String cp_docspath = "docs/" + this.getAdapterName();
|
String cp_docspath = "docs/" + this.getAdapterName();
|
||||||
Optional<Content<?>> bundled_docs = NBIO.local().pathname(dev_docspath, cp_docspath).first();
|
Optional<Content<?>> bundled_docs = NBIO.local().pathname(dev_docspath, cp_docspath).first();
|
||||||
bundled_docs.map(Content::asPath).ifPresent(docs::addContentsOf);
|
bundled_docs.map(Content::asPath).ifPresent(docs::addContentsOf);
|
||||||
|
|
||||||
Optional<Content<?>> maindoc = NBIO.local().pathname("/src/main/resources/" + this.getAdapterName() + ".md", this.getAdapterName() + ".md").first();
|
Optional<Content<?>> maindoc = NBIO.local().pathname("/src/main/resources/" + this.getAdapterName() + ".md", this.getAdapterName() + ".md").first();
|
||||||
|
|
||||||
maindoc.map(Content::asPath).ifPresent(docs::addPath);
|
maindoc.map(Content::asPath).ifPresent(docs::addPath);
|
||||||
|
|
||||||
return docs.asDocsBinder();
|
return docs.asDocsBinder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provide the simple name for this [DriverAdapter] implementation, derived from the
|
||||||
|
/// required [Service] annotation.
|
||||||
default String getAdapterName() {
|
default String getAdapterName() {
|
||||||
Service svc = this.getClass().getAnnotation(Service.class);
|
Service svc = this.getClass().getAnnotation(Service.class);
|
||||||
if (svc == null) {
|
if (svc == null) {
|
||||||
@ -220,31 +211,41 @@ public interface DriverAdapter<OPTYPE extends CycleOp<?>, SPACETYPE extends Spac
|
|||||||
return svc.selector();
|
return svc.selector();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicate the level of testing and muturity for the current adapter. This is not actively used
|
||||||
|
/// and may be removed.
|
||||||
|
/// @deprecated
|
||||||
default Maturity getAdapterMaturity() {
|
default Maturity getAdapterMaturity() {
|
||||||
return this.getClass().getAnnotation(Service.class).maturity();
|
return this.getClass().getAnnotation(Service.class).maturity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// The function returned by [#getSpaceFunc(ParsedOp)] provides access to a cache of all stateful objects needed
|
||||||
* <p>The cache of all objects needed within a single instance
|
/// within a single instance of a DriverAdapter. These are generally things needed by operations, or things
|
||||||
* of a DriverAdapter which are not operations. These are generally
|
/// needed during the construction of operations. Typically, a space is where you store a native driver instance
|
||||||
* things needed by operations, or things needed during the
|
/// which is expected to be created/initialized once and reused within an application. Generally, users can
|
||||||
* construction of operations.</p>
|
/// think of __space__ as __driver instance__, or __client instance__, although there are driver adapters that
|
||||||
*
|
/// do things other than wrap native drivers and clients.
|
||||||
* <p>During Adapter Initialization, Op Mapping, Op Synthesis, or Op Execution,
|
///
|
||||||
* you may need access to the objects in (the or a) space cache. You can build the
|
/// The value of the op field `space` is used to customize the instancing behavior of spaces. If none is provided
|
||||||
* type of context needed and then provide this function to provide new instances
|
/// by the user, then only a singular space will be created for a given adapter in an activity. This is normal,
|
||||||
* when needed.</p>
|
/// and what most users will expect to do. However, customizing the space selector can be a powerful way to test
|
||||||
*
|
/// any system with high logical concurrency. For example, each instance of a native driver will typically
|
||||||
* <p>The function returned by this method is specialized to the space mapping
|
/// maintain its own thread or connection pools, cached resources and so on. ( Unless the developers of
|
||||||
* logic in the op template. Specifically, it uses whatever binding is set on a given
|
/// said native driver are breaking encapsulation by using global singletons in the runtime, which is highly
|
||||||
* op template for the <em>space</em> op field. If none are provided, then this
|
/// frowned upon.) The spaces feature allows any nosqlbench workload to be easily converted into an unreasonably parallel
|
||||||
* becomes a short-circuit for the default '0'. If a non-numeric binding is provided,
|
/// client topology test with a single change. It works the same way for any adapter or protocol supported by
|
||||||
* then an interstitial mapping is added which converts the {@link Object#toString()}
|
/// nosqlbench.
|
||||||
* value to ordinals using a hash map. This is less optimal by far than using
|
///
|
||||||
* any binding that produces a {@link Number}.</p>
|
/// The value of the op field `space` should be a [Number] type. [Number#intValue()] is used to determine which
|
||||||
*
|
/// space instance is, if needed, initialized first, and then returned. If users provide a non-[Number] type,
|
||||||
* @return A cache of named objects
|
/// then an enumerating layer is added inline to convert any such value to an integer, which is less optimal.
|
||||||
*/
|
///
|
||||||
|
/// During op mapping or dispensing, you may need access to state held by a driver-specific implementation of
|
||||||
|
/// [SPACETYPE]. In the initialization phase, you only have access to the space function itself.
|
||||||
|
/// This is important to maintain a boundary betwen the explicitly stateless and stateful parts of the
|
||||||
|
/// runtime. To use the space, incorporate the space function into the lambdas which produce the operation to be
|
||||||
|
/// executed. This is typically done in the construtor of the related [OpDispenser].
|
||||||
|
///
|
||||||
|
/// @return A cache of named objects
|
||||||
public LongFunction<SPACETYPE> getSpaceFunc(ParsedOp pop);
|
public LongFunction<SPACETYPE> getSpaceFunc(ParsedOp pop);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,9 @@ import io.nosqlbench.nb.api.components.core.NBNamedElement;
|
|||||||
* in testing scenarios. Within the operations for an adapter, the space
|
* in testing scenarios. Within the operations for an adapter, the space
|
||||||
* may be needed, for example, to construct prepared statements, or other
|
* may be needed, for example, to construct prepared statements, or other
|
||||||
* 'session-attached' objects. Put any state that you would normally
|
* 'session-attached' objects. Put any state that you would normally
|
||||||
* associate with an instance of a native driver into a space, and use
|
* associate with an instance of a native driver into a space.
|
||||||
* the {@link DriverAdapter#getSpaceCache()} to access it when needed.</P>
|
* A function to access the cycle-specific space instance is provided where
|
||||||
|
* you might needed, such as in the mapping or dispensing APIs.
|
||||||
*/
|
*/
|
||||||
public interface Space extends NBNamedElement, AutoCloseable {
|
public interface Space extends NBNamedElement, AutoCloseable {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user