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 org.cache2k.StorageConfiguration;
026
027import java.util.ArrayList;
028import java.util.HashMap;
029import java.util.LinkedHashMap;
030import java.util.List;
031import java.util.Map;
032
033/**
034 * Simple storage implementation, just uses a hashmap. Usable for testing and as a
035 * tiny storage implementation example.
036 *
037 * @author Jens Wilke; created: 2014-06-21
038 */
039public class ByReferenceHeapStorageImpl implements CacheStorage {
040
041  StorageConfiguration<Void> config;
042  CacheStorageContext context;
043  HashMap<Object, HeapEntry> entries;
044
045  public void open(CacheStorageContext ctx, StorageConfiguration<Void> cfg) {
046    context = ctx;
047    config = cfg;
048    final int entryCapacity = cfg.getEntryCapacity();
049    if (entryCapacity == Integer.MAX_VALUE) {
050      entries = new HashMap<Object, HeapEntry>();
051    } else {
052      entries = new LinkedHashMap<Object, HeapEntry>(100, .75F, true) {
053
054        @Override
055        protected boolean removeEldestEntry(Map.Entry<Object, HeapEntry> _eldest) {
056          if (getEntryCount() > entryCapacity) {
057            context.notifyExpired(_eldest.getValue());
058            return true;
059          }
060          return false;
061        }
062      };
063    }
064
065  }
066
067  @Override
068  public synchronized StorageEntry get(Object key) throws Exception {
069    return entries.get(key);
070  }
071
072  @Override
073  public void put(StorageEntry e) throws Exception {
074    HeapEntry he = new HeapEntry();
075    he.key = e.getKey();
076    he.value = e.getValueOrException();
077    he.updated = e.getCreatedOrUpdated();
078    he.entryExpiry = e.getEntryExpiryTime();
079    he.valueExpiry = e.getValueExpiryTime();
080    synchronized (this) {
081      entries.put(e.getKey(), he);
082    }
083  }
084
085  @Override
086  public synchronized boolean remove(Object key) throws Exception {
087    return entries.remove(key) != null;
088  }
089
090  @Override
091  public synchronized boolean contains(Object key) throws Exception {
092    return entries.containsKey(key);
093  }
094
095  @Override
096  public synchronized void clear() throws Exception {
097    entries.clear();
098  }
099
100  @Override
101  public void close() throws Exception {
102    entries = null;
103  }
104
105  @Override
106  public void visit(VisitContext ctx, EntryFilter f, EntryVisitor v) throws Exception {
107    List<StorageEntry> l = new ArrayList<StorageEntry>();
108    synchronized (this) {
109      for (StorageEntry e : entries.values()) {
110        if (f.shouldInclude(e.getKey())) {
111          l.add(e);
112        }
113      }
114    }
115    for (StorageEntry e : l) {
116      if (f.shouldInclude(e.getKey())) {
117        v.visit(e);
118      }
119    }
120  }
121
122  @Override
123  public synchronized int getEntryCount() {
124    return entries.size();
125  }
126
127  static class HeapEntry implements StorageEntry {
128    Object key;
129    Object value;
130    long updated;
131    long valueExpiry;
132    long entryExpiry;
133
134    @Override
135    public Object getKey() {
136      return key;
137    }
138
139    @Override
140    public Object getValueOrException() {
141      return value;
142    }
143
144    @Override
145    public long getCreatedOrUpdated() {
146      return updated;
147    }
148
149    @Override
150    public long getValueExpiryTime() {
151      return valueExpiry;
152    }
153
154    @Override
155    public long getEntryExpiryTime() {
156      return entryExpiry;
157    }
158  }
159
160  public static class Provider
161    extends CacheStorageProviderWithVoidConfig implements ByReferenceHeapStorage {
162
163    @Override
164    public ByReferenceHeapStorageImpl create(CacheStorageContext ctx, StorageConfiguration<Void> cfg) {
165      ByReferenceHeapStorageImpl st = new ByReferenceHeapStorageImpl();
166      st.open(ctx, cfg);
167      return st;
168    }
169
170  }
171
172}