boolean remove(Object value, Codec codec, RedisConnection conn) { while (true) { conn.sync(RedisCommands.WATCH, getName()); BinarySearchResult<V> res = binarySearch((V) value, codec, conn); if (res.getIndex() < 0) { conn.sync(RedisCommands.UNWATCH); return false; } if (res.getIndex() == 0) { conn.sync(RedisCommands.MULTI); conn.sync(codec, RedisCommands.LPOP, getName()); if (((List<Object>) conn.sync(codec, RedisCommands.EXEC)).size() == 1) { return true; } } List<Object> tail = conn.sync(codec, RedisCommands.LRANGE, getName(), res.getIndex() + 1, size()); conn.sync(RedisCommands.MULTI); conn.sync(RedisCommands.LTRIM, getName(), 0, res.getIndex() - 1); if (tail.isEmpty()) { if (((List<Object>) conn.sync(codec, RedisCommands.EXEC)).size() == 1) { return true; } } else { tail.add(0, getName()); conn.sync(codec, RedisCommands.RPUSH, tail.toArray()); if (((List<Object>) conn.sync(codec, RedisCommands.EXEC)).size() == 2) { return true; } } } }
/** * Binary search algorithm * * @param value * @param connection * @param lowerIndex * @param upperIndex * @return */ private BinarySearchResult<V> binarySearch( V value, Codec codec, RedisConnection connection, int lowerIndex, int upperIndex) { while (lowerIndex <= upperIndex) { int index = lowerIndex + (upperIndex - lowerIndex) / 2; V res = getAtIndex(codec, index, connection); int cmp = comparator.compare(value, res); if (cmp == 0) { BinarySearchResult<V> indexRes = new BinarySearchResult<V>(); indexRes.setIndex(index); return indexRes; } else if (cmp < 0) { upperIndex = index - 1; } else { lowerIndex = index + 1; } } BinarySearchResult<V> indexRes = new BinarySearchResult<V>(); indexRes.setIndex(-(lowerIndex + 1)); return indexRes; }
boolean add(V value, Codec codec, RedisConnection connection) { while (true) { connection.sync(RedisCommands.WATCH, getName(), getComparatorKeyName()); checkComparator(connection); Long version = getCurrentVersion(codec, connection); BinarySearchResult<V> res = binarySearch(value, codec, connection); if (res.getIndex() < 0) { // System.out.println("index: " + res.getIndex() + " value: " + value); if (!version.equals(getCurrentVersion(codec, connection))) { connection.sync(RedisCommands.UNWATCH); continue; } // NewScore newScore = calcNewScore(res.getIndex(), connection); // if (!version.equals(getCurrentVersion(simpleConnection))) { // connection.unwatch(); // continue; // } // // String leftScoreKey = getScoreKeyName(newScore.getLeftScore()); // String rightScoreKey = getScoreKeyName(newScore.getRightScore()); // // if (simpleConnection.setnx(leftScoreKey, 1)) { // if (!version.equals(getCurrentVersion(simpleConnection))) { // connection.unwatch(); // // connection.del(leftScoreKey); // continue; // } // if (rightScoreKey != null) { // // if (!simpleConnection.setnx(rightScoreKey, 1)) { // connection.unwatch(); // // connection.del(leftScoreKey); // continue; // } // } // } else { // connection.unwatch(); // continue; // } V pivot = null; boolean before = false; int index = -(res.getIndex() + 1); if (index < size()) { before = true; pivot = connection.sync(codec, RedisCommands.LINDEX, getName(), index); } connection.sync(RedisCommands.MULTI); if (index >= size()) { connection.sync(codec, RedisCommands.RPUSH, getName(), value); } else { connection.sync( codec, RedisCommands.LINSERT, getName(), before ? "BEFORE" : "AFTER", pivot, value); } // System.out.println("adding: " + newScore.getScore() + " " + value); // connection.zadd(getName(), newScore.getScore(), value); // if (rightScoreKey != null) { // connection.del(leftScoreKey, rightScoreKey); // } else { // connection.del(leftScoreKey); // } connection.sync(RedisCommands.INCR, getCurrentVersionKey()); List<Object> re = connection.sync(codec, RedisCommands.EXEC); if (re.size() == 2) { // System.out.println("index: " + index + " value: " + value + " pivot: // " + pivot); return true; // Number val = (Number) re.get(0); // Long delCount = (Long) re.get(1); // if (rightScoreKey != null) { // if (delCount != 2) { // throw new IllegalStateException(); // } // } else { // if (delCount != 1) { // throw new IllegalStateException(); // } // } // return val != null && val.intValue() > 0; } } else { connection.sync(RedisCommands.UNWATCH); return false; } } }