001package org.cache2k.storage;
002
003/*
004 * #%L
005 * cache2k core package
006 * %%
007 * Copyright (C) 2000 - 2015 headissue GmbH, Munich
008 * %%
009 * This program is free software: you can redistribute it and/or modify
010 * it under the terms of the GNU General Public License as
011 * published by the Free Software Foundation, either version 3 of the 
012 * License, or (at your option) any later version.
013 * 
014 * This program is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017 * GNU General Public License for more details.
018 * 
019 * You should have received a copy of the GNU General Public 
020 * License along with this program.  If not, see
021 * <http://www.gnu.org/licenses/gpl-3.0.html>.
022 * #L%
023 */
024
025import java.io.IOException;
026import java.util.concurrent.ExecutorService;
027
028/**
029 * An interface for persistent or off heap storage for a cache.
030 *
031 * @author Jens Wilke; created: 2014-04-03
032 */
033public interface CacheStorage {
034
035  /**
036   * Retrieve the entry from the storage. If there is no mapping for the
037   * key, null is returned.
038   *
039   * <p>Depending on the cache configuration,  an exception on get is not severe.
040   * The cache will try other sources or return null.
041   */
042  public StorageEntry get(Object key) throws Exception;
043
044  /**
045   * Stores the entry in the storage. The entry instance is solely for transferring
046   * the data, no reference may be hold within the storage to it. The callee takes
047   * care that the entry data is consistent during the put method call.
048   *
049   * <p/>If a put operation fails an implementation should try to remove an
050   * existing entry bound to the key and then throw the exception.
051   *
052   * @throws IOException may be thrown if hope is lost
053   */
054  public void put(StorageEntry e) throws Exception;
055
056  public boolean remove(Object key) throws Exception;
057
058  /**
059   * Returns true if there is a mapping for the key.
060   *
061   * <p>An exception on contains is not severe. The cache will try other sources or
062   * return null.
063   */
064  public boolean contains(Object key) throws Exception;
065
066  /**
067   * Remove all entries from the cache and free resources. This operation is called
068   * when there is no other operation concurrently executed on this storage instance.
069   *
070   * <p/>When a Cache.clear() is initiated there is no obligation to send a
071   * CacheStorage.clear() to the persisted storage. Alternatively, all objects can
072   * be removed via remove().
073   */
074  public void clear() throws Exception;
075
076  /**
077   * Free all resources and stop operations immediately.
078   */
079  public void close() throws Exception;
080
081  /**
082   * Iterate over all stored entries and call the entry visitor. It is generally safe to
083   * return expired entries. If {@link org.cache2k.storage.PurgeableStorage} is not
084   * implemented, returning expired entries is a must, to support the generic purge
085   * algorithm.
086   *
087   * <p/>If the {@link ExecutorService} is used, the method may return immediately without
088   * the waiting for all threads to finish. This is done by the caller, when needed.
089   */
090  public void visit(VisitContext ctx, EntryFilter f, EntryVisitor v) throws Exception;
091
092  public int getEntryCount();
093
094  public static interface MultiThreadedContext {
095
096    /**
097     * A private executor service for this operation to run in multiple threads.
098     * The use of {@link ExecutorService#awaitTermination(long, java.util.concurrent.TimeUnit)} ()}
099     * waits only for threads started within the visit operation. Multiple calls to
100     * this method return the identical instance.
101     *
102     * <p>When using {@link java.util.concurrent.Callable} a thrown exception in within the
103     * task leads to an abort of the operation, see {@link #abortOnException(Throwable)}.
104     *
105     * <p>The methods
106     * {@link java.util.concurrent.ExecutorService#invokeAll(java.util.Collection, long, java.util.concurrent.TimeUnit)},
107     * {@link java.util.concurrent.ExecutorService#invokeAny(java.util.Collection)},
108     * {@link java.util.concurrent.ExecutorService#invokeAny(java.util.Collection, long, java.util.concurrent.TimeUnit)}
109     * are or may not be supported by the provided implementation.
110     */
111    ExecutorService getExecutorService();
112
113    /**
114     * If threads are started by using {@link #getExecutorService()} waits for termination
115     * or tries to stop threads immediately if {@link #shouldStop()} is true. This is also done
116     * automatically when the visit method exists.
117     */
118    void awaitTermination() throws InterruptedException;
119
120    /**
121     * True if the operation should stop immediately. Used e.g. during
122     * application shutdown.
123     */
124    boolean shouldStop();
125
126    /**
127     * If an exception cannot be handled, this method aborts the operation and
128     * propagates the exception to the operation client. Multiple exceptions can
129     * occur, since the operation is multi thread. Only the first is propagated.
130     * After this method is called {@link #shouldStop()} is true.
131     */
132    void abortOnException(Throwable ex);
133
134  }
135
136  interface EntryFilter {
137
138     boolean shouldInclude(Object _key);
139
140  }
141
142  interface VisitContext extends MultiThreadedContext {
143
144    /**
145     * True if entries should have metadata. If false, only the key will be set.
146     * Storage implementations may ignore this and always send the metadata.
147     */
148    boolean needMetaData();
149
150    /**
151     * True if entries should have the value field set with the storage contents.
152     * Storage implementations may ignore this and always send the metadata.
153     */
154    boolean needValue();
155
156  }
157
158  interface EntryVisitor {
159
160    void visit(StorageEntry e) throws Exception;
161
162  }
163
164}