001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.caching.impl;
017:
018: import org.geotools.caching.InternalStore;
019:
020: import org.geotools.feature.Feature;
021:
022: import java.util.Collection;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.Random;
026:
027: /** In-memory implementation of InternalStore, using a HashMap storage.
028: *
029: * Overflow is directed to another InternalStore, so we can chain InternalStore.
030: * (eg. Memory -> Disk -> ...)
031: *
032: * When maximum capacity is reached, randomly make room for new features,
033: * and write removed features to overflow store.
034: *
035: * @author Christophe Rousson, SoC 2007, CRG-ULAVAL
036: *
037: */
038: public class HashMapInternalStore implements InternalStore {
039: private final InternalStore overflow;
040: private final int capacity;
041: private final HashMap buffer;
042: private int count = 0;
043: private final Random rand = new Random();
044:
045: /**
046: * @param capacity
047: * @param overflow
048: */
049: public HashMapInternalStore(int capacity, InternalStore overflow) {
050: this .overflow = overflow;
051: this .capacity = capacity;
052: this .buffer = new HashMap();
053: }
054:
055: /* (non-Javadoc)
056: * @see org.geotools.caching.InternalStore#clear()
057: */
058: public void clear() {
059: buffer.clear();
060: count = 0;
061: }
062:
063: /* (non-Javadoc)
064: * @see org.geotools.caching.InternalStore#contains(org.geotools.feature.Feature)
065: */
066: public boolean contains(final Feature f) {
067: return buffer.containsKey(f.getID());
068: }
069:
070: /*
071: * (non-Javadoc)
072: *
073: * @see org.geotools.caching.InternalStore#contains(java.lang.String)
074: */
075: public boolean contains(String featureId) {
076: return buffer.containsKey(featureId);
077: }
078:
079: /* (non-Javadoc)
080: * @see org.geotools.caching.InternalStore#get(java.lang.String)
081: *
082: * TODO don't return null.
083: *
084: */
085: public Feature get(final String featureId) {
086: Feature ret = null;
087:
088: if (buffer.containsKey(featureId)) {
089: ret = (Feature) buffer.get(featureId);
090: } else {
091: if (overflow != null) {
092: ret = overflow.get(featureId);
093:
094: if (ret != null) {
095: put(ret);
096: }
097: }
098: }
099:
100: return ret;
101: }
102:
103: /* (non-Javadoc)
104: * @see org.geotools.caching.InternalStore#getAll()
105: */
106: public Collection getAll() {
107: return buffer.values();
108: }
109:
110: /* (non-Javadoc)
111: * @see org.geotools.caching.InternalStore#put(org.geotools.feature.Feature)
112: */
113: public void put(final Feature f) {
114: // assert capacity > count ;
115: if (count == capacity) {
116: evict();
117: }
118:
119: buffer.put(f.getID(), f);
120: count++;
121: }
122:
123: /* (non-Javadoc)
124: * @see org.geotools.caching.InternalStore#remove(java.lang.String)
125: */
126: public void remove(final String featureId) {
127: buffer.remove(featureId);
128: count--;
129: }
130:
131: /** Random eviction strategy.
132: * Remove an arbitrary feature from store,
133: * and put removed in features in overflow InternalStore
134: *
135: */
136: protected void evict() {
137: int entry = rand.nextInt(buffer.size());
138: Iterator it = buffer.keySet().iterator();
139:
140: for (int i = 0; i < (entry - 1); i++) {
141: it.next();
142: }
143:
144: String id = (String) it.next();
145:
146: if (overflow != null) {
147: overflow.put(get(id));
148: }
149:
150: remove(id);
151: }
152:
153: /* class Entry {
154: static final short DIRTY = 0;
155: static final short FROM_SOURCE = 1;
156: static final short FROM_CACHE = 2;
157: Feature f;
158: short state = 1;
159: public Entry(Feature f) {
160: this.f = f;
161: }
162: } */
163: }
|