Merge from upstream/master.
This commit is contained in:
@@ -3,7 +3,7 @@ apply plugin: 'maven'
|
|||||||
|
|
||||||
group = 'redis.clients'
|
group = 'redis.clients'
|
||||||
archiveBaseName = 'jedis'
|
archiveBaseName = 'jedis'
|
||||||
version = '1.0.0-RC3'
|
version = '1.0.0-RC5.1'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -23,4 +23,4 @@ uploadArchives {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package redis.clients.jedis;
|
package redis.clients.jedis;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import redis.clients.util.RedisInputStream;
|
||||||
import java.io.DataInputStream;
|
import redis.clients.util.RedisOutputStream;
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
@@ -15,8 +15,8 @@ public class Connection {
|
|||||||
private int port = Protocol.DEFAULT_PORT;
|
private int port = Protocol.DEFAULT_PORT;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
private Protocol protocol = new Protocol();
|
private Protocol protocol = new Protocol();
|
||||||
private DataOutputStream outputStream;
|
private RedisOutputStream outputStream;
|
||||||
private DataInputStream inputStream;
|
private RedisInputStream inputStream;
|
||||||
private int pipelinedCommands = 0;
|
private int pipelinedCommands = 0;
|
||||||
private int timeout = 2000;
|
private int timeout = 2000;
|
||||||
|
|
||||||
@@ -50,9 +50,13 @@ public class Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Connection sendCommand(String name, String... args) {
|
protected Connection sendCommand(String name, String... args) {
|
||||||
if (!isConnected()) {
|
try {
|
||||||
throw new JedisException("Please connect Jedis before using it.");
|
connect();
|
||||||
}
|
} catch (UnknownHostException e) {
|
||||||
|
throw new JedisException("Could not connect to redis-server", e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new JedisException("Could not connect to redis-server", e);
|
||||||
|
}
|
||||||
protocol.sendCommand(outputStream, name, args);
|
protocol.sendCommand(outputStream, name, args);
|
||||||
pipelinedCommands++;
|
pipelinedCommands++;
|
||||||
return this;
|
return this;
|
||||||
@@ -87,9 +91,8 @@ public class Connection {
|
|||||||
if (!isConnected()) {
|
if (!isConnected()) {
|
||||||
socket = new Socket(host, port);
|
socket = new Socket(host, port);
|
||||||
socket.setSoTimeout(timeout);
|
socket.setSoTimeout(timeout);
|
||||||
outputStream = new DataOutputStream(socket.getOutputStream());
|
outputStream = new RedisOutputStream(socket.getOutputStream());
|
||||||
inputStream = new DataInputStream(new BufferedInputStream(socket
|
inputStream = new RedisInputStream(socket.getInputStream());
|
||||||
.getInputStream()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +128,7 @@ public class Connection {
|
|||||||
|
|
||||||
public int getIntegerReply() {
|
public int getIntegerReply() {
|
||||||
pipelinedCommands--;
|
pipelinedCommands--;
|
||||||
return (Integer) protocol.read(inputStream);
|
return ((Integer) protocol.read(inputStream)).intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -148,4 +151,4 @@ public class Connection {
|
|||||||
}
|
}
|
||||||
return all;
|
return all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -467,7 +467,7 @@ public class Jedis {
|
|||||||
checkIsInMulti();
|
checkIsInMulti();
|
||||||
client.zincrby(key, score, member);
|
client.zincrby(key, score, member);
|
||||||
String newscore = client.getBulkReply();
|
String newscore = client.getBulkReply();
|
||||||
return Double.valueOf(newscore);
|
return Double.valueOf(newscore).doubleValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int zrank(String key, String member) {
|
public int zrank(String key, String member) {
|
||||||
@@ -513,7 +513,7 @@ public class Jedis {
|
|||||||
checkIsInMulti();
|
checkIsInMulti();
|
||||||
client.zscore(key, member);
|
client.zscore(key, member);
|
||||||
String score = client.getBulkReply();
|
String score = client.getBulkReply();
|
||||||
return Double.valueOf(score);
|
return Double.valueOf(score).doubleValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Transaction multi() {
|
public Transaction multi() {
|
||||||
@@ -684,9 +684,8 @@ public class Jedis {
|
|||||||
Set<Tuple> set = new LinkedHashSet<Tuple>();
|
Set<Tuple> set = new LinkedHashSet<Tuple>();
|
||||||
Iterator<String> iterator = membersWithScores.iterator();
|
Iterator<String> iterator = membersWithScores.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
set
|
set.add(new Tuple(iterator.next(), Double.valueOf(iterator.next())
|
||||||
.add(new Tuple(iterator.next(), Double.valueOf(iterator
|
.doubleValue()));
|
||||||
.next())));
|
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,8 @@ public class JedisException extends RuntimeException {
|
|||||||
public JedisException(IOException e) {
|
public JedisException(IOException e) {
|
||||||
super(e);
|
super(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JedisException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,10 +51,10 @@ public abstract class JedisPubSub {
|
|||||||
do {
|
do {
|
||||||
List<Object> reply = client.getObjectMultiBulkReply();
|
List<Object> reply = client.getObjectMultiBulkReply();
|
||||||
if (reply.get(0).equals("subscribe")) {
|
if (reply.get(0).equals("subscribe")) {
|
||||||
subscribedChannels = (Integer) reply.get(2);
|
subscribedChannels = ((Integer) reply.get(2)).intValue();
|
||||||
onSubscribe((String) reply.get(1), subscribedChannels);
|
onSubscribe((String) reply.get(1), subscribedChannels);
|
||||||
} else if (reply.get(0).equals("unsubscribe")) {
|
} else if (reply.get(0).equals("unsubscribe")) {
|
||||||
subscribedChannels = (Integer) reply.get(2);
|
subscribedChannels = ((Integer) reply.get(2)).intValue();
|
||||||
onUnsubscribe((String) reply.get(1), subscribedChannels);
|
onUnsubscribe((String) reply.get(1), subscribedChannels);
|
||||||
} else if (reply.get(0).equals("message")) {
|
} else if (reply.get(0).equals("message")) {
|
||||||
onMessage((String) reply.get(1), (String) reply.get(2));
|
onMessage((String) reply.get(1), (String) reply.get(2));
|
||||||
@@ -62,10 +62,10 @@ public abstract class JedisPubSub {
|
|||||||
onPMessage((String) reply.get(1), (String) reply.get(2),
|
onPMessage((String) reply.get(1), (String) reply.get(2),
|
||||||
(String) reply.get(3));
|
(String) reply.get(3));
|
||||||
} else if (reply.get(0).equals("psubscribe")) {
|
} else if (reply.get(0).equals("psubscribe")) {
|
||||||
subscribedChannels = (Integer) reply.get(2);
|
subscribedChannels = ((Integer) reply.get(2)).intValue();
|
||||||
onPSubscribe((String) reply.get(1), subscribedChannels);
|
onPSubscribe((String) reply.get(1), subscribedChannels);
|
||||||
} else if (reply.get(0).equals("punsubscribe")) {
|
} else if (reply.get(0).equals("punsubscribe")) {
|
||||||
subscribedChannels = (Integer) reply.get(2);
|
subscribedChannels = ((Integer) reply.get(2)).intValue();
|
||||||
onPUnsubscribe((String) reply.get(1), subscribedChannels);
|
onPUnsubscribe((String) reply.get(1), subscribedChannels);
|
||||||
} else {
|
} else {
|
||||||
throw new JedisException("Unknown message type: "
|
throw new JedisException("Unknown message type: "
|
||||||
|
|||||||
@@ -1,179 +1,118 @@
|
|||||||
package redis.clients.jedis;
|
package redis.clients.jedis;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import redis.clients.util.RedisInputStream;
|
||||||
import java.io.DataOutputStream;
|
import redis.clients.util.RedisOutputStream;
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.Charset;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Protocol {
|
import static redis.clients.util.RedisOutputStream.CHARSET;
|
||||||
public static final Charset CHARSET = Charset.forName("UTF-8");
|
|
||||||
|
public final class Protocol {
|
||||||
|
|
||||||
public static final String DOLLAR = "$";
|
|
||||||
public static final String ASTERISK = "*";
|
|
||||||
public static final String PLUS = "+";
|
|
||||||
public static final String MINUS = "-";
|
|
||||||
public static final String COLON = ":";
|
|
||||||
public static final String COMMAND_DELIMITER = "\r\n";
|
|
||||||
public static final byte[] COMMAND_DELIMITER_BYTES = "\r\n"
|
|
||||||
.getBytes(CHARSET);
|
|
||||||
public static final int DEFAULT_PORT = 6379;
|
public static final int DEFAULT_PORT = 6379;
|
||||||
|
|
||||||
public static final byte DOLLAR_BYTE = DOLLAR.getBytes(CHARSET)[0];
|
public static final byte DOLLAR_BYTE = '$';
|
||||||
public static final byte ASTERISK_BYTE = ASTERISK.getBytes(CHARSET)[0];
|
public static final byte ASTERISK_BYTE = '*';
|
||||||
public static final byte PLUS_BYTE = PLUS.getBytes(CHARSET)[0];
|
public static final byte PLUS_BYTE = '+';
|
||||||
public static final byte MINUS_BYTE = MINUS.getBytes(CHARSET)[0];
|
public static final byte MINUS_BYTE = '-';
|
||||||
public static final byte COLON_BYTE = COLON.getBytes(CHARSET)[0];
|
public static final byte COLON_BYTE = ':';
|
||||||
|
|
||||||
public void sendCommand(DataOutputStream os, String name, String... args) {
|
public void sendCommand(RedisOutputStream os, String name, String... args) {
|
||||||
StringBuilder sb = new StringBuilder();
|
try {
|
||||||
sb.append(ASTERISK);
|
os.write(ASTERISK_BYTE);
|
||||||
sb.append((new Integer(args.length + 1)).toString());
|
os.writeIntCrLf(args.length + 1);
|
||||||
sb.append(COMMAND_DELIMITER);
|
os.write(DOLLAR_BYTE);
|
||||||
sb.append(DOLLAR);
|
os.writeIntCrLf(name.length());
|
||||||
sb.append((new Integer(name.length())).toString());
|
os.writeAsciiCrLf(name);
|
||||||
sb.append(COMMAND_DELIMITER);
|
|
||||||
sb.append(name);
|
|
||||||
sb.append(COMMAND_DELIMITER);
|
|
||||||
|
|
||||||
for (String arg : args) {
|
for (String str : args) {
|
||||||
int size = arg.getBytes(CHARSET).length;
|
os.write(DOLLAR_BYTE);
|
||||||
|
final int size = RedisOutputStream.utf8Length(str);
|
||||||
sb.append(DOLLAR);
|
os.writeIntCrLf(size);
|
||||||
sb.append((new Integer(size)).toString());
|
if (size == str.length())
|
||||||
sb.append(COMMAND_DELIMITER);
|
os.writeAsciiCrLf(str);
|
||||||
sb.append(arg);
|
else {
|
||||||
sb.append(COMMAND_DELIMITER);
|
os.writeUtf8CrLf(str);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
try {
|
os.flush();
|
||||||
os.write(sb.toString().getBytes(CHARSET));
|
} catch (IOException e) {
|
||||||
/*
|
throw new JedisException(e);
|
||||||
os.write(ASTERISK_BYTE);
|
}
|
||||||
os.write((new Integer(args.length + 1)).toString()
|
|
||||||
.getBytes(CHARSET));
|
|
||||||
os.write(COMMAND_DELIMITER_BYTES);
|
|
||||||
os.write(DOLLAR_BYTE);
|
|
||||||
os.write((new Integer(name.length())).toString().getBytes(CHARSET));
|
|
||||||
os.write(COMMAND_DELIMITER_BYTES);
|
|
||||||
os.write(name.getBytes(CHARSET));
|
|
||||||
os.write(COMMAND_DELIMITER_BYTES);
|
|
||||||
|
|
||||||
for (String arg : args) {
|
|
||||||
byte[] barg = arg.getBytes(CHARSET);
|
|
||||||
|
|
||||||
os.write(DOLLAR_BYTE);
|
|
||||||
os.write((new Integer(barg.length)).toString()
|
|
||||||
.getBytes(CHARSET));
|
|
||||||
os.write(COMMAND_DELIMITER_BYTES);
|
|
||||||
os.write(barg);
|
|
||||||
os.write(COMMAND_DELIMITER_BYTES);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new JedisException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processError(DataInputStream is) {
|
private void processError(RedisInputStream is) {
|
||||||
String message = readLine(is);
|
String message = is.readLine();
|
||||||
throw new JedisException(message);
|
throw new JedisException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readLine(DataInputStream is) {
|
private Object process(RedisInputStream is) {
|
||||||
byte b;
|
try {
|
||||||
byte c;
|
byte b = is.readByte();
|
||||||
StringBuilder sb = new StringBuilder();
|
if (b == MINUS_BYTE) {
|
||||||
|
processError(is);
|
||||||
try {
|
} else if (b == ASTERISK_BYTE) {
|
||||||
while ((b = is.readByte()) != -1) {
|
return processMultiBulkReply(is);
|
||||||
if (b == '\r') {
|
} else if (b == COLON_BYTE) {
|
||||||
c = is.readByte();
|
return processInteger(is);
|
||||||
if (c == '\n') {
|
} else if (b == DOLLAR_BYTE) {
|
||||||
break;
|
return processBulkReply(is);
|
||||||
}
|
} else if (b == PLUS_BYTE) {
|
||||||
sb.append((char) b);
|
return processStatusCodeReply(is);
|
||||||
sb.append((char) c);
|
} else {
|
||||||
} else {
|
throw new JedisException("Unknown reply: " + (char) b);
|
||||||
sb.append((char) b);
|
}
|
||||||
}
|
} catch (IOException e) {
|
||||||
}
|
throw new JedisException(e);
|
||||||
} catch (IOException e) {
|
}
|
||||||
throw new JedisException(e);
|
return null;
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object process(DataInputStream is) {
|
private String processStatusCodeReply(RedisInputStream is) {
|
||||||
try {
|
return is.readLine();
|
||||||
byte b = is.readByte();
|
|
||||||
if (b == MINUS_BYTE) {
|
|
||||||
processError(is);
|
|
||||||
} else if (b == ASTERISK_BYTE) {
|
|
||||||
return processMultiBulkReply(is);
|
|
||||||
} else if (b == COLON_BYTE) {
|
|
||||||
return processInteger(is);
|
|
||||||
} else if (b == DOLLAR_BYTE) {
|
|
||||||
return processBulkReply(is);
|
|
||||||
} else if (b == PLUS_BYTE) {
|
|
||||||
return processStatusCodeReply(is);
|
|
||||||
} else {
|
|
||||||
throw new JedisException("Unknown reply: " + (char) b);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new JedisException(e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object processStatusCodeReply(DataInputStream is) {
|
private String processBulkReply(RedisInputStream is) {
|
||||||
String ret = null;
|
int len = Integer.parseInt(is.readLine());
|
||||||
ret = readLine(is);
|
if (len == -1) {
|
||||||
return ret;
|
return null;
|
||||||
|
}
|
||||||
|
byte[] read = new byte[len];
|
||||||
|
int offset = 0;
|
||||||
|
try {
|
||||||
|
while (offset < len) {
|
||||||
|
offset += is.read(read, offset, (len - offset));
|
||||||
|
}
|
||||||
|
// read 2 more bytes for the command delimiter
|
||||||
|
is.readByte();
|
||||||
|
is.readByte();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new JedisException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String(read, CHARSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object processBulkReply(DataInputStream is) {
|
private Integer processInteger(RedisInputStream is) {
|
||||||
int len = Integer.parseInt(readLine(is));
|
String num = is.readLine();
|
||||||
if (len == -1) {
|
return Integer.valueOf(num);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
byte[] read = new byte[len];
|
|
||||||
int offset = 0;
|
|
||||||
try {
|
|
||||||
while(offset < len) {
|
|
||||||
offset += is.read(read, offset, (len - offset));
|
|
||||||
}
|
|
||||||
// read 2 more bytes for the command delimiter
|
|
||||||
is.read();
|
|
||||||
is.read();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new JedisException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new String(read, CHARSET);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object processInteger(DataInputStream is) {
|
private List<Object> processMultiBulkReply(RedisInputStream is) {
|
||||||
int ret = 0;
|
int num = Integer.parseInt(is.readLine());
|
||||||
String num = readLine(is);
|
if (num == -1) {
|
||||||
ret = Integer.parseInt(num);
|
return null;
|
||||||
return ret;
|
}
|
||||||
|
List<Object> ret = new ArrayList<Object>(num);
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
ret.add(process(is));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object processMultiBulkReply(DataInputStream is) {
|
public Object read(RedisInputStream is) {
|
||||||
int num = Integer.parseInt(readLine(is));
|
return process(is);
|
||||||
if (num == -1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
List<Object> ret = new ArrayList<Object>();
|
|
||||||
for (int i = 0; i < num; i++) {
|
|
||||||
ret.add(process(is));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object read(DataInputStream is) {
|
|
||||||
return process(is);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ public abstract class FixedResourcePool<T> {
|
|||||||
*/
|
*/
|
||||||
private LinkedBlockingQueue<Wrapper<T>> availableQueue;
|
private LinkedBlockingQueue<Wrapper<T>> availableQueue;
|
||||||
private LinkedBlockingQueue<Wrapper<T>> repairQueue;
|
private LinkedBlockingQueue<Wrapper<T>> repairQueue;
|
||||||
private HashMap<T, Wrapper<T>> inUse = new HashMap<T, Wrapper<T>>();
|
private final HashMap<T, Wrapper<T>> inUse = new HashMap<T, Wrapper<T>>();
|
||||||
private RepairThread[] repairThreads;
|
private RepairThread[] repairThreads;
|
||||||
private Timer t;
|
private Timer t;
|
||||||
private boolean initializated = false;
|
private boolean initializated = false;
|
||||||
|
|||||||
106
src/main/java/redis/clients/util/RedisInputStream.java
Normal file
106
src/main/java/redis/clients/util/RedisInputStream.java
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009-2010 MBTE Sweden AB.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package redis.clients.util;
|
||||||
|
|
||||||
|
import redis.clients.jedis.JedisException;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class RedisInputStream extends FilterInputStream {
|
||||||
|
|
||||||
|
protected final byte buf[];
|
||||||
|
|
||||||
|
protected int count, limit;
|
||||||
|
|
||||||
|
public RedisInputStream(InputStream in, int size) {
|
||||||
|
super(in);
|
||||||
|
if (size <= 0) {
|
||||||
|
throw new IllegalArgumentException("Buffer size <= 0");
|
||||||
|
}
|
||||||
|
buf = new byte[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedisInputStream(InputStream in) {
|
||||||
|
this(in, 8192);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte readByte () throws IOException {
|
||||||
|
if(count == limit) {
|
||||||
|
fill ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf[count++];
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readLine() {
|
||||||
|
int b;
|
||||||
|
byte c;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
if(count == limit) {
|
||||||
|
fill ();
|
||||||
|
}
|
||||||
|
if(limit == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
b = buf[count++];
|
||||||
|
if (b == '\r') {
|
||||||
|
if(count == limit) {
|
||||||
|
fill ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(limit == -1) {
|
||||||
|
sb.append((char) b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = buf[count++];
|
||||||
|
if (c == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sb.append((char) b);
|
||||||
|
sb.append((char) c);
|
||||||
|
} else {
|
||||||
|
sb.append((char) b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new JedisException(e);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b, int off, int len) throws IOException {
|
||||||
|
if(count == limit) {
|
||||||
|
fill ();
|
||||||
|
if(limit == -1)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
final int length = Math.min(limit - count, len);
|
||||||
|
System.arraycopy(buf, count, b, off, length);
|
||||||
|
count += length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fill () throws IOException {
|
||||||
|
limit = in.read(buf);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
228
src/main/java/redis/clients/util/RedisOutputStream.java
Normal file
228
src/main/java/redis/clients/util/RedisOutputStream.java
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
package redis.clients.util;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class implements a buffered output stream without synchronization
|
||||||
|
* There are also special operations like in-place string encoding.
|
||||||
|
* This stream fully ignore mark/reset and should not be used outside Jedis
|
||||||
|
*/
|
||||||
|
public final class RedisOutputStream extends FilterOutputStream {
|
||||||
|
protected final byte buf[];
|
||||||
|
|
||||||
|
protected int count;
|
||||||
|
public static final Charset CHARSET = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
public RedisOutputStream(OutputStream out) {
|
||||||
|
this(out, 8192);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedisOutputStream(OutputStream out, int size) {
|
||||||
|
super(out);
|
||||||
|
if (size <= 0) {
|
||||||
|
throw new IllegalArgumentException("Buffer size <= 0");
|
||||||
|
}
|
||||||
|
buf = new byte[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flushBuffer() throws IOException {
|
||||||
|
if (count > 0) {
|
||||||
|
out.write(buf, 0, count);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int b) throws IOException {
|
||||||
|
buf[count++] = (byte) b;
|
||||||
|
if (count == buf.length) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte b[], int off, int len) throws IOException {
|
||||||
|
if (len >= buf.length) {
|
||||||
|
flushBuffer();
|
||||||
|
out.write(b, off, len);
|
||||||
|
} else {
|
||||||
|
if (len >= buf.length - count) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(b, off, buf, count, len);
|
||||||
|
count += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeAsciiCrLf(String in) throws IOException {
|
||||||
|
final int size = in.length();
|
||||||
|
|
||||||
|
for (int i = 0; i != size; ++i) {
|
||||||
|
buf[count++] = (byte) in.charAt(i);
|
||||||
|
if (count == buf.length) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeCrLf();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSurrogate(char ch) {
|
||||||
|
return ch >= Character.MIN_SURROGATE && ch <= Character.MAX_SURROGATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int utf8Length (String str) {
|
||||||
|
int strLen = str.length(), utfLen = 0;
|
||||||
|
for(int i = 0; i != strLen; ++i) {
|
||||||
|
char c = str.charAt(i);
|
||||||
|
if (c < 0x80) {
|
||||||
|
utfLen++;
|
||||||
|
} else if (c < 0x800) {
|
||||||
|
utfLen += 2;
|
||||||
|
} else if (isSurrogate(c)) {
|
||||||
|
i++;
|
||||||
|
utfLen += 4;
|
||||||
|
} else {
|
||||||
|
utfLen += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return utfLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeCrLf() throws IOException {
|
||||||
|
if (2 >= buf.length - count) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[count++] = '\r';
|
||||||
|
buf[count++] = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeUtf8CrLf(String str) throws IOException {
|
||||||
|
int strLen = str.length();
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < strLen; i++) {
|
||||||
|
char c = str.charAt(i);
|
||||||
|
if (!(c < 0x80)) break;
|
||||||
|
buf[count++] = (byte) c;
|
||||||
|
if(count == buf.length) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < strLen; i++) {
|
||||||
|
char c = str.charAt(i);
|
||||||
|
if (c < 0x80) {
|
||||||
|
buf[count++] = (byte) c;
|
||||||
|
if(count == buf.length) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
} else if (c < 0x800) {
|
||||||
|
if(2 < buf.length - count) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
buf[count++] = (byte)(0xc0 | (c >> 6));
|
||||||
|
buf[count++] = (byte)(0x80 | (c & 0x3f));
|
||||||
|
} else if (isSurrogate(c)) {
|
||||||
|
if(4 < buf.length - count) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
int uc = Character.toCodePoint(c, str.charAt(i++));
|
||||||
|
buf[count++] = ((byte)(0xf0 | ((uc >> 18))));
|
||||||
|
buf[count++] = ((byte)(0x80 | ((uc >> 12) & 0x3f)));
|
||||||
|
buf[count++] = ((byte)(0x80 | ((uc >> 6) & 0x3f)));
|
||||||
|
buf[count++] = ((byte)(0x80 | (uc & 0x3f)));
|
||||||
|
} else {
|
||||||
|
if(3 < buf.length - count) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
buf[count++] =((byte)(0xe0 | ((c >> 12))));
|
||||||
|
buf[count++] =((byte)(0x80 | ((c >> 6) & 0x3f)));
|
||||||
|
buf[count++] =((byte)(0x80 | (c & 0x3f)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeCrLf();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE};
|
||||||
|
|
||||||
|
private final static byte[] DigitTens = {
|
||||||
|
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
||||||
|
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
|
||||||
|
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
|
||||||
|
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
|
||||||
|
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
|
||||||
|
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
|
||||||
|
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
|
||||||
|
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
|
||||||
|
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
|
||||||
|
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static byte[] DigitOnes = {
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static byte[] digits = {
|
||||||
|
'0', '1', '2', '3', '4', '5',
|
||||||
|
'6', '7', '8', '9', 'a', 'b',
|
||||||
|
'c', 'd', 'e', 'f', 'g', 'h',
|
||||||
|
'i', 'j', 'k', 'l', 'm', 'n',
|
||||||
|
'o', 'p', 'q', 'r', 's', 't',
|
||||||
|
'u', 'v', 'w', 'x', 'y', 'z'
|
||||||
|
};
|
||||||
|
|
||||||
|
public void writeIntCrLf(int value) throws IOException {
|
||||||
|
if (value < 0) {
|
||||||
|
write('-');
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
while (value > sizeTable[size])
|
||||||
|
size++;
|
||||||
|
|
||||||
|
size++;
|
||||||
|
if (size >= buf.length - count) {
|
||||||
|
flushBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
int q, r;
|
||||||
|
int charPos = count + size;
|
||||||
|
|
||||||
|
while (value >= 65536) {
|
||||||
|
q = value / 100;
|
||||||
|
r = value - ((q << 6) + (q << 5) + (q << 2));
|
||||||
|
value = q;
|
||||||
|
buf[--charPos] = DigitOnes[r];
|
||||||
|
buf[--charPos] = DigitTens[r];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; ;) {
|
||||||
|
q = (value * 52429) >>> (16 + 3);
|
||||||
|
r = value - ((q << 3) + (q << 1));
|
||||||
|
buf[--charPos] = digits[r];
|
||||||
|
value = q;
|
||||||
|
if (value == 0) break;
|
||||||
|
}
|
||||||
|
count += size;
|
||||||
|
|
||||||
|
writeCrLf();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException {
|
||||||
|
flushBuffer();
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,12 +6,11 @@ import java.util.Map;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisException;
|
|
||||||
import redis.clients.jedis.Protocol;
|
|
||||||
import redis.clients.jedis.tests.commands.JedisCommandTestBase;
|
import redis.clients.jedis.tests.commands.JedisCommandTestBase;
|
||||||
|
import redis.clients.util.RedisOutputStream;
|
||||||
|
|
||||||
public class JedisTest extends JedisCommandTestBase {
|
public class JedisTest extends JedisCommandTestBase {
|
||||||
@Test(expected = JedisException.class)
|
@Test
|
||||||
public void useWithoutConnecting() {
|
public void useWithoutConnecting() {
|
||||||
Jedis jedis = new Jedis("localhost");
|
Jedis jedis = new Jedis("localhost");
|
||||||
jedis.dbSize();
|
jedis.dbSize();
|
||||||
@@ -24,11 +23,11 @@ public class JedisTest extends JedisCommandTestBase {
|
|||||||
bigdata[b] = (byte) ((byte) b % 255);
|
bigdata[b] = (byte) ((byte) b % 255);
|
||||||
}
|
}
|
||||||
Map<String, String> hash = new HashMap<String, String>();
|
Map<String, String> hash = new HashMap<String, String>();
|
||||||
hash.put("data", new String(bigdata, Protocol.CHARSET));
|
hash.put("data", new String(bigdata, RedisOutputStream.CHARSET));
|
||||||
|
|
||||||
String status = jedis.hmset("foo", hash);
|
String status = jedis.hmset("foo", hash);
|
||||||
assertEquals("OK", status);
|
assertEquals("OK", status);
|
||||||
assertEquals(hash, jedis.hgetAll("foo"));
|
assertEquals(hash, jedis.hgetAll("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package redis.clients.jedis.tests;
|
|||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PipedInputStream;
|
import java.io.PipedInputStream;
|
||||||
@@ -16,6 +15,8 @@ import junit.framework.Assert;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import redis.clients.jedis.Protocol;
|
import redis.clients.jedis.Protocol;
|
||||||
|
import redis.clients.util.RedisInputStream;
|
||||||
|
import redis.clients.util.RedisOutputStream;
|
||||||
|
|
||||||
public class ProtocolTest extends Assert {
|
public class ProtocolTest extends Assert {
|
||||||
@Test
|
@Test
|
||||||
@@ -25,7 +26,7 @@ public class ProtocolTest extends Assert {
|
|||||||
PipedOutputStream pos = new PipedOutputStream(pis);
|
PipedOutputStream pos = new PipedOutputStream(pis);
|
||||||
|
|
||||||
Protocol protocol = new Protocol();
|
Protocol protocol = new Protocol();
|
||||||
protocol.sendCommand(new DataOutputStream(pos), "GET", "SOMEKEY");
|
protocol.sendCommand(new RedisOutputStream(pos), "GET", "SOMEKEY");
|
||||||
|
|
||||||
pos.close();
|
pos.close();
|
||||||
String expectedCommand = "*2\r\n$3\r\nGET\r\n$7\r\nSOMEKEY\r\n";
|
String expectedCommand = "*2\r\n$3\r\nGET\r\n$7\r\nSOMEKEY\r\n";
|
||||||
@@ -43,7 +44,7 @@ public class ProtocolTest extends Assert {
|
|||||||
public void bulkReply() {
|
public void bulkReply() {
|
||||||
InputStream is = new ByteArrayInputStream("$6\r\nfoobar\r\n".getBytes());
|
InputStream is = new ByteArrayInputStream("$6\r\nfoobar\r\n".getBytes());
|
||||||
Protocol protocol = new Protocol();
|
Protocol protocol = new Protocol();
|
||||||
String response = (String) protocol.read(new DataInputStream(is));
|
String response = (String) protocol.read(new RedisInputStream(is));
|
||||||
assertEquals("foobar", response);
|
assertEquals("foobar", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,9 +52,8 @@ public class ProtocolTest extends Assert {
|
|||||||
public void fragmentedBulkReply() {
|
public void fragmentedBulkReply() {
|
||||||
FragmentedByteArrayInputStream fis = new FragmentedByteArrayInputStream("$30\r\n012345678901234567890123456789\r\n".getBytes());
|
FragmentedByteArrayInputStream fis = new FragmentedByteArrayInputStream("$30\r\n012345678901234567890123456789\r\n".getBytes());
|
||||||
Protocol protocol = new Protocol();
|
Protocol protocol = new Protocol();
|
||||||
String response = (String) protocol.read(new DataInputStream(fis));
|
String response = (String) protocol.read(new RedisInputStream(fis));
|
||||||
assertEquals("012345678901234567890123456789", response);
|
assertEquals("012345678901234567890123456789", response);
|
||||||
assertEquals(3, fis.getReadMethodCallCount());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ public class ProtocolTest extends Assert {
|
|||||||
public void nullBulkReply() {
|
public void nullBulkReply() {
|
||||||
InputStream is = new ByteArrayInputStream("$-1\r\n".getBytes());
|
InputStream is = new ByteArrayInputStream("$-1\r\n".getBytes());
|
||||||
Protocol protocol = new Protocol();
|
Protocol protocol = new Protocol();
|
||||||
String response = (String) protocol.read(new DataInputStream(is));
|
String response = (String) protocol.read(new RedisInputStream(is));
|
||||||
assertEquals(null, response);
|
assertEquals(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ public class ProtocolTest extends Assert {
|
|||||||
public void singleLineReply() {
|
public void singleLineReply() {
|
||||||
InputStream is = new ByteArrayInputStream("+OK\r\n".getBytes());
|
InputStream is = new ByteArrayInputStream("+OK\r\n".getBytes());
|
||||||
Protocol protocol = new Protocol();
|
Protocol protocol = new Protocol();
|
||||||
String response = (String) protocol.read(new DataInputStream(is));
|
String response = (String) protocol.read(new RedisInputStream(is));
|
||||||
assertEquals("OK", response);
|
assertEquals("OK", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ public class ProtocolTest extends Assert {
|
|||||||
public void integerReply() {
|
public void integerReply() {
|
||||||
InputStream is = new ByteArrayInputStream(":123\r\n".getBytes());
|
InputStream is = new ByteArrayInputStream(":123\r\n".getBytes());
|
||||||
Protocol protocol = new Protocol();
|
Protocol protocol = new Protocol();
|
||||||
int response = (Integer) protocol.read(new DataInputStream(is));
|
int response = (Integer) protocol.read(new RedisInputStream(is));
|
||||||
assertEquals(123, response);
|
assertEquals(123, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ public class ProtocolTest extends Assert {
|
|||||||
.getBytes());
|
.getBytes());
|
||||||
Protocol protocol = new Protocol();
|
Protocol protocol = new Protocol();
|
||||||
List<String> response = (List<String>) (List<?>) protocol
|
List<String> response = (List<String>) (List<?>) protocol
|
||||||
.read(new DataInputStream(is));
|
.read(new RedisInputStream(is));
|
||||||
List<String> expected = new ArrayList<String>();
|
List<String> expected = new ArrayList<String>();
|
||||||
expected.add("foo");
|
expected.add("foo");
|
||||||
expected.add("bar");
|
expected.add("bar");
|
||||||
@@ -103,7 +103,7 @@ public class ProtocolTest extends Assert {
|
|||||||
.getBytes());
|
.getBytes());
|
||||||
protocol = new Protocol();
|
protocol = new Protocol();
|
||||||
List<Object> response2 = (List<Object>) protocol
|
List<Object> response2 = (List<Object>) protocol
|
||||||
.read(new DataInputStream(is));
|
.read(new RedisInputStream(is));
|
||||||
List<Object> expected2 = new ArrayList<Object>();
|
List<Object> expected2 = new ArrayList<Object>();
|
||||||
expected2.add("foo");
|
expected2.add("foo");
|
||||||
expected2.add("OK");
|
expected2.add("OK");
|
||||||
@@ -122,7 +122,7 @@ public class ProtocolTest extends Assert {
|
|||||||
InputStream is = new ByteArrayInputStream("*-1\r\n".getBytes());
|
InputStream is = new ByteArrayInputStream("*-1\r\n".getBytes());
|
||||||
Protocol protocol = new Protocol();
|
Protocol protocol = new Protocol();
|
||||||
List<String> response = (List<String>) protocol
|
List<String> response = (List<String>) protocol
|
||||||
.read(new DataInputStream(is));
|
.read(new RedisInputStream(is));
|
||||||
assertNull(response);
|
assertNull(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user