- new concurrent score map using atom operation from java concurrency classes - redesigned difference beween StaticScore and Dynamic Score into ScoreMap and ReversibleScoreMap allowed that many classes can now use simple ScoreMap Objects which can be used better in concurrent environments using the ConcurrentScoreMap - switched from DynamicScore to ConcurrentScoreMap usage wherever possible git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@7586 6c8d7289-2bf4-0310-a012-ef5d649a1542pull/1/head
parent
a564230c48
commit
8f11d3a5bb
@ -0,0 +1,205 @@
|
||||
/**
|
||||
* ConcurrentScoreMap
|
||||
* Copyright 2010 by Michael Peter Christen, mc@yacy.net, Frankfurt am Main, Germany
|
||||
* First released 13.03.2011 at http://yacy.net
|
||||
*
|
||||
* $LastChangedDate: 2011-03-08 02:51:51 +0100 (Di, 08 Mrz 2011) $
|
||||
* $LastChangedRevision: 7567 $
|
||||
* $LastChangedBy: low012 $
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program in the file lgpl21.txt
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.yacy.cora.storage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
|
||||
public class ConcurrentScoreMap<E> implements ScoreMap<E> {
|
||||
|
||||
protected final ConcurrentHashMap<E, AtomicLong> map; // a mapping from a reference to the cluster key
|
||||
private long gcount;
|
||||
|
||||
public ConcurrentScoreMap() {
|
||||
map = new ConcurrentHashMap<E, AtomicLong>();
|
||||
gcount = 0;
|
||||
}
|
||||
|
||||
public synchronized void clear() {
|
||||
map.clear();
|
||||
gcount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* shrink the cluster to a demanded size
|
||||
* @param maxsize
|
||||
*/
|
||||
public void shrinkToMaxSize(int maxsize) {
|
||||
if (this.map.size() <= maxsize) return;
|
||||
int minScore = getMinScore();
|
||||
while (this.map.size() > maxsize) {
|
||||
minScore++;
|
||||
shrinkToMinScore(minScore);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* shrink the cluster in such a way that the smallest score is equal or greater than a given minScore
|
||||
* @param minScore
|
||||
*/
|
||||
public void shrinkToMinScore(int minScore) {
|
||||
Iterator<Map.Entry<E, AtomicLong>> i = this.map.entrySet().iterator();
|
||||
Map.Entry<E, AtomicLong> entry;
|
||||
while (i.hasNext()) {
|
||||
entry = i.next();
|
||||
if (entry.getValue().intValue() < minScore) i.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public long totalCount() {
|
||||
return gcount;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
public void inc(final E obj) {
|
||||
if (obj == null) return;
|
||||
|
||||
// use atomic operations
|
||||
this.map.putIfAbsent(obj, new AtomicLong(0));
|
||||
this.map.get(obj).incrementAndGet();
|
||||
|
||||
// increase overall counter
|
||||
gcount++;
|
||||
}
|
||||
|
||||
public void dec(final E obj) {
|
||||
if (obj == null) return;
|
||||
|
||||
// use atomic operations
|
||||
this.map.putIfAbsent(obj, new AtomicLong(0));
|
||||
this.map.get(obj).decrementAndGet();
|
||||
|
||||
// increase overall counter
|
||||
gcount--;
|
||||
}
|
||||
|
||||
public void set(final E obj, final int newScore) {
|
||||
if (obj == null) return;
|
||||
|
||||
// use atomic operations
|
||||
this.map.putIfAbsent(obj, new AtomicLong(0));
|
||||
this.map.get(obj).set(newScore);
|
||||
|
||||
// increase overall counter
|
||||
gcount += newScore;
|
||||
}
|
||||
|
||||
public void inc(final E obj, final int incrementScore) {
|
||||
if (obj == null) return;
|
||||
|
||||
// use atomic operations
|
||||
this.map.putIfAbsent(obj, new AtomicLong(0));
|
||||
this.map.get(obj).addAndGet(incrementScore);
|
||||
|
||||
// increase overall counter
|
||||
gcount += incrementScore;
|
||||
}
|
||||
|
||||
public void dec(final E obj, final int decrementScore) {
|
||||
inc(obj, -decrementScore);
|
||||
}
|
||||
|
||||
public int delete(final E obj) {
|
||||
// deletes entry and returns previous score
|
||||
if (obj == null) return 0;
|
||||
final AtomicLong score = this.map.remove(obj);
|
||||
if (score == null) return 0;
|
||||
|
||||
// decrease overall counter
|
||||
gcount -= score.intValue();
|
||||
return score.intValue();
|
||||
}
|
||||
|
||||
public boolean containsKey(final E obj) {
|
||||
return this.map.containsKey(obj);
|
||||
}
|
||||
|
||||
public int get(final E obj) {
|
||||
if (obj == null) return 0;
|
||||
final AtomicLong score = this.map.get(obj);
|
||||
if (score == null) return 0;
|
||||
return score.intValue();
|
||||
}
|
||||
|
||||
private int getMinScore() {
|
||||
if (this.map.isEmpty()) return -1;
|
||||
int minScore = Integer.MAX_VALUE;
|
||||
for (Map.Entry<E, AtomicLong> entry: this.map.entrySet()) if (entry.getValue().intValue() < minScore) {
|
||||
minScore = entry.getValue().intValue();
|
||||
}
|
||||
return minScore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return map.toString();
|
||||
}
|
||||
|
||||
public Iterator<E> keys(boolean up) {
|
||||
// re-organize entries
|
||||
TreeMap<IntScore, Set<E>> m = new TreeMap<IntScore, Set<E>>();
|
||||
Set<E> s;
|
||||
IntScore is;
|
||||
for (Map.Entry<E, AtomicLong> entry: this.map.entrySet()) {
|
||||
is = new IntScore(entry.getValue().intValue());
|
||||
s = m.get(is);
|
||||
if (s == null) {
|
||||
s = new HashSet<E>();
|
||||
s.add(entry.getKey());
|
||||
m.put(is, s);
|
||||
} else {
|
||||
s.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
// flatten result
|
||||
List<E> l = new ArrayList<E>(m.size());
|
||||
for (Set<E> f: m.values()) {
|
||||
for (E e: f) l.add(e);
|
||||
}
|
||||
if (up) return l.iterator();
|
||||
|
||||
// optionally reverse list
|
||||
List<E> r = new ArrayList<E>(l.size());
|
||||
for (int i = l.size() - 1; i >= 0; i--) r.add(l.get(i));
|
||||
return r.iterator();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,280 @@
|
||||
/**
|
||||
* ScoreMap
|
||||
* Copyright 2010 by Michael Peter Christen, mc@yacy.net, Frankfurt am Main, Germany
|
||||
* First released 14.10.2010 at http://yacy.net
|
||||
*
|
||||
* $LastChangedDate$
|
||||
* $LastChangedRevision$
|
||||
* $LastChangedBy$
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program in the file lgpl21.txt
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.yacy.cora.storage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
||||
public class OrderedScoreMap<E> implements ScoreMap<E> {
|
||||
|
||||
protected final Map<E, IntScore> map; // a mapping from a reference to the cluster key
|
||||
private long gcount;
|
||||
|
||||
public OrderedScoreMap(Comparator<? super E> comparator) {
|
||||
if (comparator == null) {
|
||||
map = new HashMap<E, IntScore>();
|
||||
} else {
|
||||
map = new TreeMap<E, IntScore>(comparator);
|
||||
}
|
||||
gcount = 0;
|
||||
}
|
||||
|
||||
public synchronized void clear() {
|
||||
map.clear();
|
||||
gcount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* shrink the cluster to a demanded size
|
||||
* @param maxsize
|
||||
*/
|
||||
public void shrinkToMaxSize(int maxsize) {
|
||||
if (this.map.size() <= maxsize) return;
|
||||
int minScore = getMinScore();
|
||||
while (this.map.size() > maxsize) {
|
||||
minScore++;
|
||||
shrinkToMinScore(minScore);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* shrink the cluster in such a way that the smallest score is equal or greater than a given minScore
|
||||
* @param minScore
|
||||
*/
|
||||
public void shrinkToMinScore(int minScore) {
|
||||
synchronized (this) {
|
||||
Iterator<Map.Entry<E, IntScore>> i = this.map.entrySet().iterator();
|
||||
Map.Entry<E, IntScore> entry;
|
||||
while (i.hasNext()) {
|
||||
entry = i.next();
|
||||
if (entry.getValue().intValue() < minScore) i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized long totalCount() {
|
||||
return gcount;
|
||||
}
|
||||
|
||||
public synchronized int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public synchronized boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
public void inc(final E obj) {
|
||||
if (obj == null) return;
|
||||
synchronized (this) {
|
||||
IntScore score = this.map.get(obj);
|
||||
if (score == null) {
|
||||
this.map.put(obj, new IntScore(1));
|
||||
} else {
|
||||
score.inc();
|
||||
}
|
||||
}
|
||||
// increase overall counter
|
||||
gcount++;
|
||||
}
|
||||
|
||||
public void dec(final E obj) {
|
||||
if (obj == null) return;
|
||||
synchronized (this) {
|
||||
IntScore score = this.map.get(obj);
|
||||
if (score == null) {
|
||||
this.map.put(obj, IntScore.valueOf(-1));
|
||||
} else {
|
||||
score.dec();
|
||||
}
|
||||
}
|
||||
// increase overall counter
|
||||
gcount--;
|
||||
}
|
||||
|
||||
public void set(final E obj, final int newScore) {
|
||||
if (obj == null) return;
|
||||
synchronized (this) {
|
||||
IntScore score = this.map.get(obj);
|
||||
if (score == null) {
|
||||
this.map.put(obj, new IntScore(1));
|
||||
} else {
|
||||
gcount -= score.intValue();
|
||||
score.set(newScore);
|
||||
}
|
||||
}
|
||||
// increase overall counter
|
||||
gcount += newScore;
|
||||
}
|
||||
|
||||
public void inc(final E obj, final int incrementScore) {
|
||||
if (obj == null) return;
|
||||
synchronized (this) {
|
||||
IntScore score = this.map.get(obj);
|
||||
if (score == null) {
|
||||
this.map.put(obj, IntScore.valueOf(incrementScore));
|
||||
} else {
|
||||
score.inc(incrementScore);
|
||||
}
|
||||
}
|
||||
// increase overall counter
|
||||
gcount += incrementScore;
|
||||
}
|
||||
|
||||
public void dec(final E obj, final int incrementScore) {
|
||||
inc(obj, -incrementScore);
|
||||
}
|
||||
|
||||
public int delete(final E obj) {
|
||||
// deletes entry and returns previous score
|
||||
if (obj == null) return 0;
|
||||
final IntScore score;
|
||||
synchronized (this) {
|
||||
score = map.remove(obj);
|
||||
if (score == null) return 0;
|
||||
}
|
||||
|
||||
// decrease overall counter
|
||||
gcount -= score.intValue();
|
||||
return score.intValue();
|
||||
}
|
||||
|
||||
public synchronized boolean containsKey(final E obj) {
|
||||
return map.containsKey(obj);
|
||||
}
|
||||
|
||||
public int get(final E obj) {
|
||||
if (obj == null) return 0;
|
||||
final IntScore score;
|
||||
synchronized (this) {
|
||||
score = map.get(obj);
|
||||
}
|
||||
if (score == null) return 0;
|
||||
return score.intValue();
|
||||
}
|
||||
|
||||
public SortedMap<E, IntScore> tailMap(E obj) {
|
||||
if (this.map instanceof TreeMap) {
|
||||
return ((TreeMap<E, IntScore>) this.map).tailMap(obj);
|
||||
}
|
||||
throw new UnsupportedOperationException("map must have comparator");
|
||||
}
|
||||
|
||||
private int getMinScore() {
|
||||
if (map.isEmpty()) return -1;
|
||||
int minScore = Integer.MAX_VALUE;
|
||||
synchronized (this) {
|
||||
for (Map.Entry<E, IntScore> entry: this.map.entrySet()) if (entry.getValue().intValue() < minScore) {
|
||||
minScore = entry.getValue().intValue();
|
||||
}
|
||||
}
|
||||
return minScore;
|
||||
}
|
||||
|
||||
/*
|
||||
public int getMaxScore() {
|
||||
if (map.isEmpty()) return -1;
|
||||
int maxScore = Integer.MIN_VALUE;
|
||||
synchronized (this) {
|
||||
for (Map.Entry<E, IntScore> entry: this.map.entrySet()) if (entry.getValue().intValue() > maxScore) {
|
||||
maxScore = entry.getValue().intValue();
|
||||
}
|
||||
}
|
||||
return maxScore;
|
||||
}
|
||||
|
||||
public E getMaxKey() {
|
||||
if (map.isEmpty()) return null;
|
||||
E maxObject = null;
|
||||
int maxScore = Integer.MIN_VALUE;
|
||||
synchronized (this) {
|
||||
for (Map.Entry<E, IntScore> entry: this.map.entrySet()) if (entry.getValue().intValue() > maxScore) {
|
||||
maxScore = entry.getValue().intValue();
|
||||
maxObject = entry.getKey();
|
||||
}
|
||||
}
|
||||
return maxObject;
|
||||
}
|
||||
|
||||
public E getMinKey() {
|
||||
if (map.isEmpty()) return null;
|
||||
E minObject = null;
|
||||
int minScore = Integer.MAX_VALUE;
|
||||
synchronized (this) {
|
||||
for (Map.Entry<E, IntScore> entry: this.map.entrySet()) if (entry.getValue().intValue() < minScore) {
|
||||
minScore = entry.getValue().intValue();
|
||||
minObject = entry.getKey();
|
||||
}
|
||||
}
|
||||
return minObject;
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return map.toString();
|
||||
}
|
||||
|
||||
public Iterator<E> keys(boolean up) {
|
||||
synchronized (this) {
|
||||
// re-organize entries
|
||||
TreeMap<IntScore, Set<E>> m = new TreeMap<IntScore, Set<E>>();
|
||||
Set<E> s;
|
||||
for (Map.Entry<E, IntScore> entry: this.map.entrySet()) {
|
||||
s = m.get(entry.getValue());
|
||||
if (s == null) {
|
||||
s = this.map instanceof TreeMap ? new TreeSet<E>(((TreeMap<E, IntScore>) this.map).comparator()) : new HashSet<E>();
|
||||
s.add(entry.getKey());
|
||||
m.put(entry.getValue(), s);
|
||||
} else {
|
||||
s.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
// flatten result
|
||||
List<E> l = new ArrayList<E>(this.map.size());
|
||||
for (Set<E> f: m.values()) {
|
||||
for (E e: f) l.add(e);
|
||||
}
|
||||
if (up) return l.iterator();
|
||||
|
||||
// optionally reverse list
|
||||
List<E> r = new ArrayList<E>(l.size());
|
||||
for (int i = l.size() - 1; i >= 0; i--) r.add(l.get(i));
|
||||
return r.iterator();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/**
|
||||
* StaticScore
|
||||
* Copyright 2010 by Michael Peter Christen, mc@yacy.net, Frankfurt am Main, Germany
|
||||
* First released 14.10.2010 at http://yacy.net
|
||||
*
|
||||
* $LastChangedDate$
|
||||
* $LastChangedRevision$
|
||||
* $LastChangedBy$
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program in the file lgpl21.txt
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.yacy.cora.storage;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public interface StaticScore<E> {
|
||||
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* shrink the cluster to a demanded size
|
||||
* @param maxsize
|
||||
*/
|
||||
public void shrinkToMaxSize(int maxsize);
|
||||
|
||||
/**
|
||||
* shrink the cluster in such a way that the smallest score is equal or greater than a given minScore
|
||||
* @param minScore
|
||||
*/
|
||||
public void shrinkToMinScore(int minScore);
|
||||
|
||||
public long totalCount();
|
||||
|
||||
public int size();
|
||||
|
||||
public boolean isEmpty();
|
||||
|
||||
public void set(final E obj, final int newScore);
|
||||
|
||||
public int delete(final E obj);
|
||||
|
||||
public boolean containsKey(final E obj);
|
||||
|
||||
public int get(final E obj);
|
||||
|
||||
public int getMaxScore();
|
||||
|
||||
public int getMinScore();
|
||||
|
||||
public E getMaxKey();
|
||||
|
||||
public E getMinKey();
|
||||
|
||||
@Override
|
||||
public String toString();
|
||||
|
||||
public Iterator<E> keys(final boolean up);
|
||||
|
||||
}
|
Loading…
Reference in new issue