001: /*
002: This source file is part of Smyle, a database library.
003: For up-to-date information, see http://www.drjava.de/smyle
004: Copyright (C) 2001 Stefan Reich (doc@drjava.de)
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; either
009: version 2.1 of the License, or (at your option) any later version.
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: You should have received a copy of the GNU Lesser General Public
017: License along with this library; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019:
020: For full license text, see doc/license/lgpl.txt in this distribution
021: */
022:
023: package drjava.smyle.core;
024:
025: import java.util.*;
026: import java.io.*;
027: import org.artsProject.mcop.*;
028:
029: public class IndexAdvisor<F> {
030: F indexedField;
031: HashMap<F, Long> fieldStats;
032: //MarDemar<F> md;
033: long initialHurdle = DEFAULT_INITIAL_HURDLE;
034: boolean frozen = false;
035:
036: static final long DEFAULT_INITIAL_HURDLE = 5000;
037:
038: public IndexAdvisor(/*MarDemar<F> md*/) {
039: //this.md = md;
040: fieldStats = new HashMap<F, Long>();
041: }
042:
043: /*public IndexAdvisor(MarDemar<F> md, ChunkManager cm, ChunkRef cr) {
044: this(md);
045: IAStats stats = new IAStats(cm.readChunk(cr));
046: for (int i = 0; i < stats.fieldStats.size(); i++) {
047: IAFieldStats fs = stats.fieldStats.get(i);
048: fieldStats.put(md.read(new Buffer(fs.field.toArray())), new Long(fs.records));
049: }
050: }*/
051:
052: /*public ChunkRef saveStats(ChunkManager cm) {
053: IAStats stats = new IAStats();
054: for (Iterator<Map.Entry<F,Long>> i = fieldStats.entrySet().iterator(); i.hasNext(); ) {
055: Map.Entry<F,Long> entry = i.next();
056: IAFieldStats fs = new IAFieldStats(entry.getValue().longValue());
057: Buffer b = new Buffer();
058: md.marshal(b, entry.getKey());
059: fs.field.set(b.toByteArray());
060: stats.fieldStats.add(fs);
061: }
062: return cm.createChunk(stats);
063: }*/
064:
065: public void collectChunks(BitSet whiteList, ChunkRef chunk) {
066: whiteList.set(chunk.index);
067: }
068:
069: /** returns the name of the field that should be indexed;
070: or null if no indices are needed */
071: public F fieldToIndex() {
072: if (frozen)
073: return indexedField;
074:
075: // find field with greatest value
076: F bestField = null;
077: long max = 0L;
078: for (Iterator<Map.Entry<F, Long>> i = fieldStats.entrySet()
079: .iterator(); i.hasNext();) {
080: Map.Entry<F, Long> entry = i.next();
081: if (entry.getValue().longValue() > max) {
082: max = entry.getValue().longValue();
083: bestField = entry.getKey();
084: }
085: }
086:
087: // check if it is worthwhile to replace current index
088: /*System.out.println("current: "+indexedField+", new: "+bestField
089: +", value="+max+", hurdle: "+hurdle());*/
090: if (bestField != null && max >= hurdle())
091: return bestField;
092: else
093: return indexedField;
094: }
095:
096: /** used by store to notify index advisor that an index has been built */
097: public void setIndexedField(F field) {
098: indexedField = field;
099: }
100:
101: /** minimum value a new fieldToIndex must have */
102: long hurdle() {
103: if (indexedField != null)
104: return getStats(indexedField) * 2;
105: else
106: return initialHurdle;
107: }
108:
109: /** notifies the advisor that a query was performed
110: @param records the number of records that were read unnecessarily */
111: // TODO: does the first argument need to be an array?
112: public void queryPerformed(F[] fields, long records) {
113: for (int i = 0; i < fields.length; i++)
114: increaseStats(fields[i], records);
115: }
116:
117: void increaseStats(F field, long n) {
118: setStats(field, getStats(field) + n);
119: }
120:
121: public long getStats(F field) {
122: Long L = fieldStats.get(field);
123: return L != null ? L.longValue() : 0L;
124: }
125:
126: void setStats(F field, long n) {
127: fieldStats.put(field, new Long(n));
128: }
129:
130: public void setInitialHurdle(long h) {
131: initialHurdle = h;
132: }
133:
134: public void freeze() {
135: frozen = true;
136: }
137:
138: public String toString() {
139: return fieldStats.toString();
140: }
141:
142: public Iterator<F> fields() {
143: return fieldStats.keySet().iterator();
144: }
145: }
|