Sorted set scores collapsed to zeros fixed. #28

pull/38/head
Nikita 11 years ago
parent 9e6ee8dadc
commit c19ed0a649

@ -18,7 +18,9 @@ package org.redisson;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.security.MessageDigest;
import java.util.Collection;
import java.util.Comparator;
@ -211,13 +213,30 @@ public class RedissonSortedSet<V> extends RedissonObject implements RSortedSet<V
}
public Iterator<V> iterator() {
double startScore;
Double startScore;
RedisConnection<Object, V> connection = connectionManager.connectionReadOp();
try {
startScore = getScoreAtIndex(0, connection);
} finally {
connectionManager.releaseRead(connection);
}
if (startScore == null) {
return new Iterator<V>() {
@Override
public boolean hasNext() {
return false;
}
@Override
public V next() {
throw new NoSuchElementException();
}
@Override
public void remove() {
}
};
}
return iterator(startScore, Double.MAX_VALUE);
}
@ -266,6 +285,7 @@ public class RedissonSortedSet<V> extends RedissonObject implements RSortedSet<V
ScoredValue<V> val = values.get(0);
value = val.value;
// System.out.println("value: " + value + " currentScore: " + currentScore);
if (values.size() > 1) {
ScoredValue<V> nextVal = values.get(1);
currentScore = nextVal.score;
@ -375,6 +395,7 @@ public class RedissonSortedSet<V> extends RedissonObject implements RSortedSet<V
}
connection.multi();
// System.out.println("adding: " + newScore.getScore() + " " + value);
connection.zadd(getName(), newScore.getScore(), value);
if (rightScoreKey != null) {
connection.del(leftScoreKey, rightScoreKey);
@ -421,16 +442,27 @@ public class RedissonSortedSet<V> extends RedissonObject implements RSortedSet<V
}
}
public static double calcIncrement(double value) {
BigDecimal b = BigDecimal.valueOf(value);
BigDecimal r = b.remainder(BigDecimal.ONE);
if (r.compareTo(BigDecimal.ZERO) == 0) {
return 1;
}
double res = 1/Math.pow(10, r.scale());
return res;
}
/**
* score for entry added before head = head / 2
* score for entry added after tail = tail + 1000000
* score for first entry = 0
* score for entry added before = head - calcIncrement(head)
* score for entry added after = tail + calcIncrement(head)
* score for entry inserted between head and tail = head + (tail - head) / 2
*
* @param index
* @param connection
* @return score for index
*/
public NewScore calcNewScore(int index, RedisConnection<Object, V> connection) {
protected NewScore calcNewScore(int index, RedisConnection<Object, V> connection) {
if (index >= 0) {
throw new IllegalStateException("index should be negative, but value is " + index);
}
@ -438,24 +470,51 @@ public class RedissonSortedSet<V> extends RedissonObject implements RSortedSet<V
Double leftScore = null;
Double rightScore = null;
double score = getScoreAtIndex(index, connection);
Double score = getScoreAtIndex(index, connection);
// check is upper postion
if (index == 0) {
if (score < 0) {
score = (double) 1000000;
if (score == null) {
// first score
score = 0D;
leftScore = score;
} else {
// before head
leftScore = score;
score = score / 2;
score = BigDecimal.valueOf(score).add(BigDecimal.valueOf(calcIncrement(score)).negate()).doubleValue();
}
} else {
leftScore = getScoreAtIndex(index-1, connection);
if (score < 0) {
score = leftScore + 1000000;
if (score == null) {
// after tail
score = BigDecimal.valueOf(leftScore).add(BigDecimal.valueOf(calcIncrement(leftScore))).doubleValue();
} else {
rightScore = score;
score = leftScore + (rightScore - leftScore) / 2;
if (rightScore < leftScore) {
double rs = rightScore;
leftScore = rs;
rightScore = leftScore;
}
double s = BigDecimal.valueOf(rightScore).add(BigDecimal.valueOf(leftScore).negate()).doubleValue();
if (s == 1) {
score = BigDecimal.valueOf(leftScore).add(BigDecimal.valueOf(0.1)).doubleValue();
} else if (s > 1) {
score = leftScore + 1;
} else if (s < 1) {
double inc = calcIncrement(s);
if (BigDecimal.valueOf(leftScore).add(BigDecimal.valueOf(inc)).compareTo(BigDecimal.valueOf(rightScore)) >= 0) {
// TODO check strange behavior
// if (leftScore + inc >= rightScore) {
if (inc == 0) {
inc = 0.1;
}
score = BigDecimal.valueOf(leftScore).add(BigDecimal.valueOf(inc).divide(BigDecimal.TEN)).doubleValue();
} else {
score = BigDecimal.valueOf(leftScore).add(BigDecimal.valueOf(inc)).doubleValue();
}
}
}
}
// System.out.println("score: " + score + " left: " + leftScore + " right: " + rightScore);
return new NewScore(leftScore, rightScore, score);
}
@ -624,10 +683,10 @@ public class RedissonSortedSet<V> extends RedissonObject implements RSortedSet<V
}
}
private double getScoreAtIndex(int index, RedisConnection<Object, V> connection) {
private Double getScoreAtIndex(int index, RedisConnection<Object, V> connection) {
List<ScoredValue<V>> res = connection.zrangeWithScores(getName(), index, index);
if (res.isEmpty()) {
return -1;
return null;
}
return res.get(0).score;
}

Loading…
Cancel
Save