All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nstream.persist.kv.KvNodePersistence Maven / Gradle / Ivy

There is a newer version: 4.12.20
Show newest version
// Copyright 2015-2024 Nstream, inc.
//
// 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 nstream.persist.kv;

import java.nio.ByteBuffer;
import java.util.TreeMap;
import nstream.persist.api.PersistenceException;
import nstream.persist.api.cache.MapBackingStore;
import nstream.persist.api.cache.NodePersistenceApi;
import nstream.persist.api.cache.ValueBackingStore;
import nstream.persist.api.kv.IoResult;
import nstream.persist.api.kv.IterationStatus;
import nstream.persist.api.kv.KeyValueBuffers;
import nstream.persist.api.kv.KvStoreApi;
import nstream.persist.api.kv.MapIterator;
import nstream.persist.kv.state.StoreState;
import swim.codec.Binary;
import swim.collections.BTree;
import swim.recon.Recon;
import swim.recon.ReconParser;
import swim.structure.Item;
import swim.structure.Value;

/**
 * Implements the core Swim store interface. The initial store instance created is the root. When the root instance is
 * closed, the underlying database will be closed also, regardless of how many subsidiary stores have been opened.
 * 

* Each instance of this type has an associated path name (for the root, this path is empty). */ class KvNodePersistence implements NodePersistenceApi, AutoCloseable { private final String node; private final KvStoreApi store; private final StoreState state; /** * Create a root store. * * @param store The underlying key-value store. * @param state State store for the states of the lanes (shared between all children of the root). */ KvNodePersistence(final KvStoreApi store, String node, StoreState state) { this.store = store; this.node = node; this.state = state; } private static Value parseFrom(ReconParser parser, ByteBuffer buffer) { final var after = parser.parseBlock(Binary.inputBuffer(buffer)); if (after.isDone()) { return after.bind(); } else { return Value.extant(); } } private static BTree initMap(MapIterator it) throws PersistenceException { final var parser = Recon.structureParser(); final TreeMap builder = new TreeMap<>(); final KeyValueBuffers buffers = new KeyValueBuffers(ByteBuffer.allocate(0), ByteBuffer.allocate(0)); while (it.hasCurrent()) { IterationStatus status = null; do { if (status != null) { if (status.keyOverflowed()) { status.getKeyRequired().ifPresentOrElse(buffers::growKey, buffers::growKey); } if (status.valueOverflowed()) { status.getValueRequired().ifPresentOrElse(buffers::growValue, buffers::growValue); } } status = it.current(buffers); } while (status.getResult() == IoResult.BufferOverflow); final var key = parseFrom(parser, buffers.getKeyBuffer()); final var value = parseFrom(parser, buffers.getValueBuffer()); builder.put(key, value); it.advance(); } return BTree.from(builder); } @Override public ValueBackingStore openValueStore(String lane) throws PersistenceException { final var id = this.store.laneId(this.node, lane); final var valueBuffer = this.store.getValue(id, null); final Value value; if (valueBuffer == null) { value = Value.extant(); } else { final var parser = Recon.structureParser().parseBlock(Binary.inputBuffer(valueBuffer)); if (parser.isDone()) { value = parser.bind(); } else { value = Value.extant(); } } return this.state.openValueState(id, value); } @Override public MapBackingStore openMapStore(String lane) throws PersistenceException { final var id = this.store.laneId(this.node, lane); final BTree contents; try (var iterator = this.store.getMap(id)) { contents = initMap(iterator); } return this.state.openMapState(id, contents); } @Override public void close() { } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy