001: // kelondroObjects.java
002: // -----------------------
003: // (C) 29.01.2007 by Michael Peter Christen; mc@anomic.de, Frankfurt a. M., Germany
004: // first published 2004 as kelondroMap on http://www.anomic.de
005: //
006: // This is a part of YaCy, a peer-to-peer based web search engine
007: //
008: // $LastChangedDate: 2006-04-02 22:40:07 +0200 (So, 02 Apr 2006) $
009: // $LastChangedRevision: 1986 $
010: // $LastChangedBy: orbiter $
011: //
012: // LICENSE
013: //
014: // This program is free software; you can redistribute it and/or modify
015: // it under the terms of the GNU General Public License as published by
016: // the Free Software Foundation; either version 2 of the License, or
017: // (at your option) any later version.
018: //
019: // This program is distributed in the hope that it will be useful,
020: // but WITHOUT ANY WARRANTY; without even the implied warranty of
021: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
022: // GNU General Public License for more details.
023: //
024: // You should have received a copy of the GNU General Public License
025: // along with this program; if not, write to the Free Software
026: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
027:
028: package de.anomic.kelondro;
029:
030: import java.io.IOException;
031: import java.util.HashMap;
032: import java.util.Iterator;
033:
034: public class kelondroObjects {
035:
036: private kelondroDyn dyn;
037: private kelondroMScoreCluster<String> cacheScore;
038: private HashMap<String, kelondroObjectsEntry> cache;
039: private long startup;
040: private int cachesize;
041:
042: public kelondroObjects(kelondroDyn dyn, int cachesize) {
043: this .dyn = dyn;
044: this .cache = new HashMap<String, kelondroObjectsEntry>();
045: this .cacheScore = new kelondroMScoreCluster<String>();
046: this .startup = System.currentTimeMillis();
047: this .cachesize = cachesize;
048: }
049:
050: public void reset() throws IOException {
051: this .dyn.reset();
052: this .cache = new HashMap<String, kelondroObjectsEntry>();
053: this .cacheScore = new kelondroMScoreCluster<String>();
054: }
055:
056: public int keySize() {
057: return dyn.row().width(0);
058: }
059:
060: public synchronized void set(String key, kelondroObjectsEntry newMap)
061: throws IOException {
062: assert (key != null);
063: assert (key.length() > 0);
064: assert (newMap != null);
065: if (cacheScore == null)
066: return; // may appear during shutdown
067:
068: // write entry
069: kelondroRA kra = dyn.getRA(key);
070: newMap.write(kra);
071: kra.close();
072:
073: // check for space in cache
074: checkCacheSpace();
075:
076: // write map to cache
077: cacheScore.setScore(key,
078: (int) ((System.currentTimeMillis() - startup) / 1000));
079: cache.put(key, newMap);
080: }
081:
082: public synchronized void remove(String key) throws IOException {
083: // update elementCount
084: if (key == null)
085: return;
086:
087: // remove from cache
088: cacheScore.deleteScore(key);
089: cache.remove(key);
090:
091: // remove from file
092: dyn.remove(key);
093: }
094:
095: public synchronized kelondroObjectsEntry get(final String key)
096: throws IOException {
097: if (key == null)
098: return null;
099: return get(key, true);
100: }
101:
102: protected synchronized kelondroObjectsEntry get(final String key,
103: final boolean storeCache) throws IOException {
104: // load map from cache
105: assert key != null;
106: if (cache == null)
107: return null; // case may appear during shutdown
108: kelondroObjectsEntry map = (kelondroObjectsEntry) cache
109: .get(key);
110: if (map != null)
111: return map;
112:
113: // load map from kra
114: if (!(dyn.existsDyn(key)))
115: return null;
116:
117: // read object
118: kelondroRA kra = dyn.getRA(key);
119: map = new kelondroObjectsMapEntry(kra);
120: kra.close();
121:
122: if (storeCache) {
123: // cache it also
124: checkCacheSpace();
125: // write map to cache
126: cacheScore
127: .setScore(
128: key,
129: (int) ((System.currentTimeMillis() - startup) / 1000));
130: cache.put(key, map);
131: }
132:
133: // return value
134: return map;
135: }
136:
137: private synchronized void checkCacheSpace() {
138: // check for space in cache
139: if (cache == null)
140: return; // may appear during shutdown
141: if (cache.size() >= cachesize) {
142: // delete one entry
143: final String delkey = (String) cacheScore.getMinObject();
144: cacheScore.deleteScore(delkey);
145: cache.remove(delkey);
146: }
147: }
148:
149: public synchronized kelondroCloneableIterator<String> keys(
150: final boolean up, final boolean rotating)
151: throws IOException {
152: // simple enumeration of key names without special ordering
153: return dyn.dynKeys(up, rotating);
154: }
155:
156: public synchronized kelondroCloneableIterator<String> keys(
157: final boolean up, final boolean rotating,
158: final byte[] firstKey, final byte[] secondKey)
159: throws IOException {
160: // simple enumeration of key names without special ordering
161: kelondroCloneableIterator<String> i = dyn.dynKeys(up, firstKey);
162: if (rotating)
163: return new kelondroRotateIterator<String>(i, secondKey, dyn
164: .sizeDyn());
165: else
166: return i;
167: }
168:
169: public synchronized objectIterator entries(final boolean up,
170: final boolean rotating) throws IOException {
171: return new objectIterator(keys(up, rotating));
172: }
173:
174: public synchronized objectIterator entries(final boolean up,
175: final boolean rotating, final byte[] firstKey,
176: final byte[] secondKey) throws IOException {
177: return new objectIterator(keys(up, rotating, firstKey,
178: secondKey));
179: }
180:
181: public synchronized int size() {
182: return dyn.sizeDyn();
183: }
184:
185: public void close() {
186: // finish queue
187: //writeWorker.terminate(true);
188:
189: cache = null;
190: cacheScore = null;
191:
192: // close file
193: dyn.close();
194: }
195:
196: public class objectIterator implements
197: Iterator<kelondroObjectsEntry> {
198: // enumerates Map-Type elements
199: // the key is also included in every map that is returned; it's key is 'key'
200:
201: Iterator<String> keyIterator;
202: boolean finish;
203:
204: public objectIterator(Iterator<String> keyIterator) {
205: this .keyIterator = keyIterator;
206: this .finish = false;
207: }
208:
209: public boolean hasNext() {
210: return (!(finish)) && (keyIterator.hasNext());
211: }
212:
213: public kelondroObjectsEntry next() {
214: final String nextKey = (String) keyIterator.next();
215: if (nextKey == null) {
216: finish = true;
217: return null;
218: }
219: try {
220: final kelondroObjectsEntry obj = get(nextKey);
221: if (obj == null)
222: throw new kelondroException(
223: "no more elements available");
224: return obj;
225: } catch (IOException e) {
226: finish = true;
227: return null;
228: }
229: }
230:
231: public void remove() {
232: throw new UnsupportedOperationException();
233: }
234: } // class mapIterator
235: }
|