/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.brooklyn.core.internal.storage; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentMap; import com.google.common.annotations.Beta; import com.google.common.annotations.VisibleForTesting; public interface BrooklynStorage { /** * Creates a reference to a value, backed by the storage-medium. If a reference with this * name has already been created, then that existing reference will be returned. * * The returned reference is a live view: changes made to the reference will be persisted, * and changes that others make will be reflected in the reference. * * The reference is thread-safe. No additional synchronization is required when getting/setting * the reference. * * @param id */ <T> Reference<T> getReference(String id); /** * Creates a list backed by the storage-medium. If a list with this name has already been * created, then that existing list will be returned. * * The returned list is not a live view. Changes are made by calling reference.set(), and * the view is refreshed by calling reference.get(). Changes are thread-safe, but callers * must be careful not to overwrite other's changes. For example, the code below could overwrite * another threads changes that are made to the map between the call to get() and the subsequent * call to set(). * * <pre> * {@code * Reference<List<String>> ref = storage.<String>createNonConcurrentList("myid"); * List<String> newval = ImmutableList.<String>builder().addAll(ref.get()).add("another").builder(); * ref.set(newval); * } * </pre> * * TODO Aled says: Is getNonConcurrentList necessary? * The purpose of this method, rather than just using * {@code Reference ref = getReference(id); ref.set(ImmutableList.of())} * is to allow control of the serialization of the things inside the list * (e.g. switching the Location object to serialize a proxy object of some sort). * I don't want us to have to do deep inspection of every object being added to any map/ref. * Feels like we can use normal serialization unless the top-level object matches an * instanceof for special things like Entity, Location, etc. * * Peter responds: * What I'm a bit scared of is that we need to write some kind of meta serialization mechanism * on top of the mechanisms provided by e.g. Hazelcast or Infinispan. Hazelcast has a very * extensive serialization library where you can plug in all kinds of serialization mechanisms. * * @param id */ @Beta <T> Reference<List<T>> getNonConcurrentList(String id); /** * Creates a map backed by the storage-medium. If a map with this name has already been * created, then that existing map will be returned. * * The returned map is a live view: changes made to the map will be persisted, and changes * that others make will be reflected in the map. * * The map is thread-safe: {@link Map#keySet()} etc will iterate over a snapshot view of the * contents. * * @param id */ <K,V> ConcurrentMap<K,V> getMap(String id); /** * Removes the data stored against this id, whether it is a map, ref or whatever. */ void remove(String id); /** * Terminates the BrooklynStorage. */ void terminate(); /** asserts that some of the storage containers which should be empty are empty; * this could do more thorough checks, but as it is it is useful to catch many leaks, * and the things which aren't empty it's much harder to check whether they should be empty! * <p> * not meant for use outwith tests */ @VisibleForTesting public boolean isMostlyEmpty(); Map<String, Object> getStorageMetrics(); }