/*
* Copyright 2016 higherfrequencytrading.com
*
* 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.
*
*/
package net.openhft.chronicle.engine;
import net.openhft.chronicle.bytes.Bytes;
import net.openhft.chronicle.bytes.BytesStore;
import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.core.OS;
import net.openhft.chronicle.core.onoes.ExceptionKey;
import net.openhft.chronicle.core.pool.ClassAliasPool;
import net.openhft.chronicle.core.values.IntValue;
import net.openhft.chronicle.engine.api.EngineReplication;
import net.openhft.chronicle.engine.api.map.MapView;
import net.openhft.chronicle.engine.api.tree.Asset;
import net.openhft.chronicle.engine.api.tree.AssetTree;
import net.openhft.chronicle.engine.api.tree.RequestContext;
import net.openhft.chronicle.engine.fs.ChronicleMapGroupFS;
import net.openhft.chronicle.engine.fs.FilePerKeyGroupFS;
import net.openhft.chronicle.engine.map.*;
import net.openhft.chronicle.engine.map.VanillaEngineReplication.RemoteNodeReplicationState;
import net.openhft.chronicle.engine.map.VanillaEngineReplication.ReplicationData;
import net.openhft.chronicle.engine.tree.HostIdentifier;
import net.openhft.chronicle.engine.tree.VanillaAssetTree;
import net.openhft.chronicle.wire.Wire;
import net.openhft.chronicle.wire.WireType;
import net.openhft.lang.model.DataValueClasses;
import org.jetbrains.annotations.NotNull;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.function.Function;
import static net.openhft.chronicle.engine.api.tree.RequestContext.requestContext;
/**
* Created by daniel on 28/05/15.
*/
public class ChronicleMapKeyValueStoreTest {
public static final String NAME = "/ChMaps/test";
private static AssetTree tree1;
private static AssetTree tree2;
private static AssetTree tree3;
private static Map<ExceptionKey, Integer> exceptions;
@BeforeClass
public static void before() throws IOException {
exceptions = Jvm.recordExceptions();
ClassAliasPool.CLASS_ALIASES.addAlias(ChronicleMapGroupFS.class);
ClassAliasPool.CLASS_ALIASES.addAlias(FilePerKeyGroupFS.class);
//Delete any files from the last run
Files.deleteIfExists(Paths.get(OS.TARGET, NAME));
tree1 = create(1, WireType.TEXT);
tree2 = create(2, WireType.TEXT);
tree3 = create(3, WireType.TEXT);
}
@AfterClass
public static void after() {
tree1.close();
tree2.close();
tree3.close();
if (!exceptions.isEmpty()) {
Jvm.dumpException(exceptions);
Assert.fail();
}
}
@NotNull
private static String fullPath(@NotNull RequestContext cxt) {
String basePath = cxt.basePath();
return basePath == null ? cxt.name() : basePath + "/" + cxt.name();
}
@NotNull
private static AssetTree create(final int hostId, Function<Bytes, Wire> writeType) {
@NotNull AssetTree tree = new VanillaAssetTree((byte) hostId)
.forTesting()
.withConfig(resourcesDir() + "/cmkvst", OS.TARGET + "/" + hostId);
tree.root().addWrappingRule(MapView.class, "map directly to KeyValueStore",
VanillaMapView::new,
AuthenticatedKeyValueStore.class);
tree.root().addLeafRule(FilePerKeyValueStore.class, "FilePerKey Map",
FilePerKeyValueStore::new);
tree.root().addLeafRule(RawKVSSubscription.class, " vanilla",
MapKVSSubscription::new);
tree.root().addLeafRule(EngineReplication.class, "Engine replication holder",
(RequestContext requestContext, Asset asset) -> new VanillaEngineReplication<>(
segment -> new FilePerKeyBasedKeyMarshallableValueStore<>(
new FilePerKeyValueStore(
requestContext(
Paths.get(fullPath(requestContext),
"perKeyReplicationData_segment" +
segment).toString()), asset),
BytesStore::toString,
s -> {
Bytes bs = BytesStore.wrap(new byte[s.length()])
.bytesForWrite();
bs.writeUtf8(s);
return bs;
},
() -> DataValueClasses.newInstance(ReplicationData.class)
),
new FilePerKeyBasedKeyMarshallableValueStore<>(
new FilePerKeyValueStore(
requestContext(
Paths.get(fullPath(requestContext),
"perRemoteNodeReplicationState")
.toString()), asset),
id -> id.getValue() + "",
id -> {
IntValue v = DataValueClasses.newInstance(IntValue.class);
v.setValue(Integer.valueOf(id));
return v;
},
() -> DataValueClasses.newInstance(RemoteNodeReplicationState.class)
),
asset.findOrCreateView(HostIdentifier.class).hostId(),
asset.findOrCreateView(FilePerKeyValueStore.class),
(kvStore, replicationEntry) -> {
if (replicationEntry.isDeleted()) {
kvStore.remove(replicationEntry.key().toString());
} else {
kvStore.put(replicationEntry.key().toString(),
replicationEntry.value());
}
},
(kvStore, key) -> kvStore.get(key.toString()),
(kvStore, key) -> kvStore.segmentFor(key.toString()),
s -> {
Bytes bs = BytesStore.wrap(new byte[s.length()])
.bytesForWrite();
bs.writeUtf8(s);
return bs;
}
));
// VanillaAssetTreeEgMain.registerTextViewofTree("host " + hostId, tree);
return tree;
}
@NotNull
public static String resourcesDir() {
String path = ChronicleMapKeyValueStoreTest.class.getProtectionDomain()
.getCodeSource().getLocation().getPath();
if (path == null)
return ".";
@NotNull String resources = new File(path).getParentFile().getParentFile() + "/src/test/resources";
return resources;
}
}