Skip to content

Commit

Permalink
Add memory as a key value storage option (#1617)
Browse files Browse the repository at this point in the history
Add `memory` as an option for `--key-value-storage`.  This is useful in
small network synchronization tests as memory is faster and is easier to
inspect via a debugger.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
  • Loading branch information
shemnon committed Dec 3, 2020
1 parent a430ea1 commit 9c22fbc
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## 20.10.3

### Additions and Improvements
* Added `memory` as an option to `--key-value-storage`. This ephemeral storage is intended for sync testing and debugging. [\#1617](https://github.com/hyperledger/besu/pull/1617)

### Bug Fixes

Expand Down
2 changes: 2 additions & 0 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
import org.hyperledger.besu.services.PicoCLIOptionsImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl;
import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin;
import org.hyperledger.besu.util.NetworkUtility;
import org.hyperledger.besu.util.PermissioningConfigurationValidator;
import org.hyperledger.besu.util.number.Fraction;
Expand Down Expand Up @@ -1226,6 +1227,7 @@ private void preparePlugins() {

// register built-in plugins
new RocksDBPlugin().register(besuPluginContext);
new InMemoryStoragePlugin().register(besuPluginContext);

besuPluginContext.registerPlugins(pluginsDir());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.services.kvstore;

import org.hyperledger.besu.plugin.BesuContext;
import org.hyperledger.besu.plugin.BesuPlugin;
import org.hyperledger.besu.plugin.services.BesuConfiguration;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.StorageService;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;

import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class InMemoryStoragePlugin implements BesuPlugin {

private static final Logger LOG = LogManager.getLogger();
private BesuContext context;
private MemoryKeyValueStorageFactory factory;
private MemoryKeyValueStorageFactory privacyFactory;

@Override
public void register(final BesuContext context) {
LOG.debug("Registering plugin");
this.context = context;

createFactoriesAndRegisterWithStorageService();

LOG.debug("Plugin registered.");
}

@Override
public void start() {
LOG.debug("Starting plugin.");
if (factory == null) {
createFactoriesAndRegisterWithStorageService();
}
}

@Override
public void stop() {
LOG.debug("Stopping plugin.");

if (factory != null) {
factory.close();
factory = null;
}

if (privacyFactory != null) {
privacyFactory.close();
privacyFactory = null;
}
}

private void createAndRegister(final StorageService service) {

factory = new MemoryKeyValueStorageFactory("memory");
privacyFactory = new MemoryKeyValueStorageFactory("memory-privacy");

service.registerKeyValueStorage(factory);
service.registerKeyValueStorage(privacyFactory);
}

private void createFactoriesAndRegisterWithStorageService() {
context
.getService(StorageService.class)
.ifPresentOrElse(
this::createAndRegister,
() -> LOG.error("Failed to register KeyValueFactory due to missing StorageService."));
}

public static class MemoryKeyValueStorageFactory implements KeyValueStorageFactory {

private final String name;
private final Map<SegmentIdentifier, InMemoryKeyValueStorage> storageMap = new HashMap<>();

public MemoryKeyValueStorageFactory(final String name) {
this.name = name;
}

@Override
public String getName() {
return name;
}

@Override
public KeyValueStorage create(
final SegmentIdentifier segment,
final BesuConfiguration configuration,
final MetricsSystem metricsSystem)
throws StorageException {
return storageMap.computeIfAbsent(segment, __ -> new InMemoryKeyValueStorage());
}

@Override
public boolean isSegmentIsolationSupported() {
return true;
}

@Override
public void close() {
storageMap.clear();
}
}
}

0 comments on commit 9c22fbc

Please sign in to comment.