Configuration
NeoEMF allows a fine customization of backends and stores through the standard EMF Resource#save()
and Resource#load()
methods.
Since NeoEMF v2.0, the configuration of stores and databases has been merged in a single class: Config
.
This interface provides common options, stores configuration and methods for building implementations.
Module-specific implementations provide specific options for their associated database, such as database configuration or data mapping strategy.
Common Configuration
Stores are used to configure NeoEMF at the application level, in-memory caching, logging, etc. They appear between EMF and the backend, in order to intercept calls or add pre/post-processing operations.
Common stores are available for all the backends, and includes:
-
Auto-saving : saves/commits the modification to the database regularly (chunk can be configured)
-
Logging : logs every calls to the database, with the concerned backend, the name of the method, the parameters and the result(s)
-
Read-only : blocks all write operations
-
Stats recording : records some statistics about the usage of the database (experimental)
-
Container caching : caches the container of accessed elements
-
Meta-class caching : caches the meta-class of accessed elements
-
Size caching : caches the size of accessed multi-valued features
-
Feature caching : caches the values of accessed features to limit database accesses
Configurations (common and module-specific) are only taken into account for a loaded or saved resources. For instance, if you want to use auto-save to create a model with massive insertions (which is strongly recommended), you will first need to save the empty resource with the associated option. Otherwis, every insertions will be saved in an in-memory database, which can cause a massive memory overhead. |
Example
In the following example, every call to MyUriFactory and MyConfig refer to a module-specific implementation of UriFactory and Config .
|
// [...]
// Create a new resource
URI uri = new MyUriFactory().createLocalUri(***);
Resource resource = resourceSet.createResource(uri);
// Create the map holding the options
Map<String, Object> options = new MyConfig()
.autosave()
.cacheContainers()
.cacheMetaclasses()
.asMap();
// Give the options to the resource
resource.save(options);
// [Perform the massive insertion here]
// Commit the modifications (if necessary)
resource.save(options);
resource.unload();
Module-Specific Configuration
As they are strongly related to each backend, there is no generic database options.
Each module provides its own implementation of:
-
UriFactory
to build and link aURI
to aBackendFactory
-
Config
to customize the backend behavior
Blueprints
Because Blueprints is an adapter that can be used for several databases, it exists several implementations:
-
BlueprintsTinkerConfig
to configure a TinkerGraph database -
BlueprintsNeo4jConfig
to configure an embedded Neo4j database
For now, the only additional configuration concern Neo4j, which can add native options with BlueprintsNeo4jConfig#addNativeOption
.
These options are not handled by NeoEMF, but processed directly by the database; see org.neo4j.graphdb.factory.GraphDatabaseSettings
for more information.
When the Blueprints implementation is a transactional database (for example the Neo4j implementation),
each modification are grouped into a transaction, that is committed when the resource is saved.
This transaction may grow significantly if many operations are performed before a resource |
MapDB / BerkeleyDB
Because MapDB and BerkeleyDB are two map-based databases, their structure and configuration are sightly identical.
For now, the only additional configuration concern the data mapping strategy, especially for multi-valued features:
-
Indices : stored separately, identified with their position (
feature:1=value1, feature:2=value2,...
) -
Arrays : grouped and stored in arrays (
feature=[1=value1, 2=value2,...]
) -
Lists : similar to a mapping with arrays, but with lists (
feature=List[1=value1, 2=value2,...]
)
NOTE: These mapping inherits from standard data mapping, available in the core component, and reusable for custom implementations.
HBase
For now, HBase have no additional configuration, but we recommended to use its specific implementation for future modifications. Because of its distributed nature, it requires some pre-requisites. They are presented in a dedicated page.