/* * 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.mgmt.persist; import java.util.Date; import java.util.List; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReadWriteLock; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityMode; import org.apache.brooklyn.util.time.Duration; import com.google.common.annotations.Beta; /** * Interface for working with persistence targets, including file system and jclouds object stores. * @author Andrea Turli */ public interface PersistenceObjectStore { /** accessor to an object/item in a {@link PersistenceObjectStore} */ public interface StoreObjectAccessor { /** gets the object, or null if not found */ String get(); byte[] getBytes(); boolean exists(); void put(String contentsToReplaceOrCreate); void append(String contentsToAppendOrCreate); void delete(); // NB: creation date is available for many blobstores but // not on java.io.File and filesystems, so it is not included here /** last modified date, null if not supported or does not exist */ Date getLastModifiedDate(); } public interface StoreObjectAccessorWithLock extends StoreObjectAccessor { /** waits for all currently scheduled write lock operations (puts, appends, and deletes) to complete; * but does not wait on or prevent subsequent modifications. * this is suitable for a model where the caller is managing synchronization. * <p> * for more complex uses, readers should <code>getLockObject().readLock().lockInterruptibly()</code> * and ensure they subsequently <code>unlock()</code> it of course. see {@link #getLockObject()}. */ void waitForCurrentWrites(Duration timeout) throws InterruptedException, TimeoutException; /** returns the underlying lock in case callers need more complex synchronization control */ ReadWriteLock getLockObject(); } /** human-readable name of this object store */ public String getSummaryName(); /** * Allows a way for an object store to be created ahead of time, and a mgmt context injected. * Currently subsequent changes are not permitted. * <p> * A {@link ManagementContext} must be supplied via constructor or this method before invoking other methods. */ @Beta public void injectManagementContext(ManagementContext managementContext); /** * Prepares the persistence store for read use and non-contentious write use, * in particular detecting whether we should clean or register a need for backup etc. * Typically called early in the setup lifecycle, after {@link #injectManagementContext(ManagementContext)}, * but before {@link #prepareForMasterUse()}. * <p> * See {@link #prepareForMasterUse()} for discussion of "contentious writes". */ @Beta public void prepareForSharedUse(PersistMode persistMode, HighAvailabilityMode highAvailabilityMode); /** * Prepares the persistence store for "contentious writes". * These are defined as those writes which might overwrite important information. * Implementations usually perform backup/versioning of the store if required. * <p> * Caller must call {@link #prepareForSharedUse(PersistMode, HighAvailabilityMode)} first * (and {@link #injectManagementContext(ManagementContext)} before that). * <p> * This is typically invoked "at the last moment" e.g. before the any such write, * mainly in order to prevent backups being made unnecessarily (e.g. if a node is standby, * or if it tries to become master but is not capable), * but also to prevent simultaneous backups which can cause problems with some stores * (only a mgmt who knows he is the master should invoke this). **/ @Beta public void prepareForMasterUse(); /** * For reading/writing data to the item at the given path. * Note that the accessor is not generally thread safe, usually does not support blocking, * and multiple instances may conflict with each other. * <p> * Clients should wrap in a dedicated {@link StoreObjectAccessorLocking} and share * if multiple threads may be accessing the store. * This method may be changed in future to allow access to a shared locking accessor. */ @Beta // TODO requiring clients to wrap and cache accessors is not very nice API, // better would be to do caching here probably, // but we've already been doing it this way above for now (Jun 2014) StoreObjectAccessor newAccessor(String path); /** create the directory at the given subPath relative to the base of this store */ void createSubPath(String subPath); /** * Lists the paths of objects contained at the given path, including the subpath. * For example, if a file-based ObjectStore is configured to write to file://path/to/root/ * then parentSubPath=entities would return the contents of /path/to/root/entities/, such as * [entities/e1, entities/e2, entities/e3]. * The returned paths values are usable in calls to {@link #newAccessor(String)}. */ List<String> listContentsWithSubPath(String subPath); /** Entirely delete the contents of this persistence location. * Use with care, primarily in tests. This will recursively wipe the indicated location. */ public void deleteCompletely(); /** * Closes all resources used by this ObjectStore. No subsequent calls should be made to the ObjectStore; * behaviour of such calls is undefined but likely to throw exceptions. */ void close(); }