Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Basic redis endpoint (only supports ping)
Heavily based on the (Apache) redis-protocol project: https://github.com/spullara/redis-protocol
- Loading branch information
Showing
18 changed files
with
714 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
cloudata-keyvalue/src/main/java/com/cloudata/keyvalue/redis/BulkRedisResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package com.cloudata.keyvalue.redis; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
import io.netty.buffer.Unpooled; | ||
|
||
import java.nio.charset.Charset; | ||
|
||
import com.google.common.base.Charsets; | ||
|
||
public class BulkRedisResponse extends RedisResponse { | ||
public static final BulkRedisResponse NIL_REPLY = new BulkRedisResponse(); | ||
|
||
public static final char MARKER = '$'; | ||
private final ByteBuf data; | ||
private final int length; | ||
|
||
private BulkRedisResponse() { | ||
this.data = null; | ||
this.length = -1; | ||
} | ||
|
||
public BulkRedisResponse(byte[] bytes) { | ||
this.data = Unpooled.wrappedBuffer(bytes); | ||
this.length = bytes.length; | ||
} | ||
|
||
public BulkRedisResponse(ByteBuf bytes) { | ||
this.data = bytes; | ||
this.length = bytes.capacity(); | ||
} | ||
|
||
// @Override | ||
// public ByteBuf data() { | ||
// return data; | ||
// } | ||
|
||
public String asAsciiString() { | ||
if (data == null) { | ||
return null; | ||
} | ||
return data.toString(Charsets.US_ASCII); | ||
} | ||
|
||
public String asUTF8String() { | ||
if (data == null) { | ||
return null; | ||
} | ||
return data.toString(Charsets.UTF_8); | ||
} | ||
|
||
public String asString(Charset charset) { | ||
if (data == null) { | ||
return null; | ||
} | ||
return data.toString(charset); | ||
} | ||
|
||
@Override | ||
public void encode(ByteBuf os) { | ||
os.writeByte(MARKER); | ||
Codec.writeLong(os, length); | ||
if (length > 0) { | ||
os.writeBytes(data); | ||
|
||
// Special case: null response does not have a CRLF | ||
os.writeBytes(CRLF); | ||
} | ||
} | ||
|
||
@Override | ||
public void encodeInline(ByteBuf os) { | ||
if (length > 0) { | ||
os.writeByte('+'); | ||
os.writeBytes(data); | ||
} | ||
os.writeBytes(CRLF); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return asUTF8String(); | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
cloudata-keyvalue/src/main/java/com/cloudata/keyvalue/redis/Codec.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package com.cloudata.keyvalue.redis; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
|
||
import java.io.IOException; | ||
|
||
public class Codec { | ||
public static final char CR = '\r'; | ||
public static final char LF = '\n'; | ||
|
||
static class Cache { | ||
private static final int cacheLow = -255; | ||
private static final int cacheHigh = 255; | ||
private static byte[][] cache; | ||
|
||
static { | ||
cache = new byte[1 + cacheHigh - cacheLow][]; | ||
for (int i = 0; i < cache.length; i++) { | ||
long v = cacheLow + i; | ||
cache[i] = Long.toString(v).getBytes(); | ||
} | ||
} | ||
} | ||
|
||
public static void writeLong(ByteBuf out, long value) { | ||
if (value >= Cache.cacheLow && value <= Cache.cacheHigh) { | ||
out.writeBytes(Cache.cache[(int) (value - Cache.cacheLow)]); | ||
} else { | ||
// TODO: Can we do much better (avoid the array)? I don't think we can... | ||
StringBuilder sb = new StringBuilder(20); | ||
sb.append(value); | ||
for (int i = 0; i < sb.length(); i++) { | ||
char c = sb.charAt(i); | ||
assert c == '-' || (c >= '0' && c <= '9'); | ||
out.writeByte(c); | ||
} | ||
} | ||
} | ||
|
||
public static long readLong(ByteBuf buf) throws IOException { | ||
long v = 0; | ||
boolean negative = false; | ||
int read = buf.readByte(); | ||
if (read == '-') { | ||
negative = true; | ||
read = buf.readByte(); | ||
} | ||
do { | ||
if (read == CR) { | ||
if (buf.readByte() == LF) { | ||
break; | ||
} | ||
} | ||
int value = read - '0'; | ||
if (value >= 0 && value < 10) { | ||
v *= 10; | ||
v += value; | ||
} else { | ||
throw new IOException("Invalid character in integer"); | ||
} | ||
read = buf.readByte(); | ||
} while (true); | ||
|
||
if (negative) { | ||
v = -v; | ||
} | ||
return v; | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
cloudata-keyvalue/src/main/java/com/cloudata/keyvalue/redis/ErrorRedisReponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.cloudata.keyvalue.redis; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
|
||
import com.google.common.base.Charsets; | ||
|
||
public class ErrorRedisReponse extends RedisResponse { | ||
public static final byte MARKER = '-'; | ||
|
||
public static final ErrorRedisReponse NOT_IMPLEMENTED = new ErrorRedisReponse("Not yet implemented"); | ||
|
||
private final String message; | ||
private final byte[] messageBytes; | ||
|
||
public ErrorRedisReponse(String message) { | ||
this.message = message; | ||
this.messageBytes = message.getBytes(Charsets.UTF_8); | ||
} | ||
|
||
// @Override | ||
// public String data() { | ||
// return message; | ||
// } | ||
|
||
@Override | ||
public void encode(ByteBuf os) { | ||
os.writeByte(MARKER); | ||
os.writeBytes(messageBytes); | ||
os.writeBytes(CRLF); | ||
} | ||
|
||
@Override | ||
public void encodeInline(ByteBuf os) { | ||
os.writeByte('-'); | ||
os.writeBytes(messageBytes); | ||
os.writeBytes(CRLF); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "ERROR:" + message; | ||
} | ||
|
||
} |
26 changes: 26 additions & 0 deletions
26
cloudata-keyvalue/src/main/java/com/cloudata/keyvalue/redis/InlineRedisResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.cloudata.keyvalue.redis; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
|
||
public class InlineRedisResponse extends RedisResponse { | ||
final RedisResponse inner; | ||
|
||
public InlineRedisResponse(RedisResponse inner) { | ||
this.inner = inner; | ||
} | ||
|
||
@Override | ||
public void encode(ByteBuf out) { | ||
if (inner == null) { | ||
out.writeBytes(CRLF); | ||
} else { | ||
inner.encodeInline(out); | ||
} | ||
} | ||
|
||
@Override | ||
public void encodeInline(ByteBuf out) { | ||
throw new IllegalStateException(); | ||
} | ||
|
||
} |
54 changes: 54 additions & 0 deletions
54
cloudata-keyvalue/src/main/java/com/cloudata/keyvalue/redis/IntegerRedisResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.cloudata.keyvalue.redis; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
|
||
public class IntegerRedisResponse extends RedisResponse { | ||
public static final char MARKER = ':'; | ||
|
||
private final long value; | ||
|
||
private static final int cacheLow = -255; | ||
private static final int cacheHigh = 255; | ||
private static IntegerRedisResponse[] cache; | ||
|
||
static { | ||
cache = new IntegerRedisResponse[1 + cacheHigh - cacheLow]; | ||
for (int i = 0; i < cache.length; i++) { | ||
cache[i + cacheLow] = new IntegerRedisResponse(i); | ||
} | ||
} | ||
|
||
public static IntegerRedisResponse valueOf(long v) { | ||
if (v >= cacheLow && v <= cacheHigh) { | ||
return cache[(int) (v - cacheLow)]; | ||
} else { | ||
return new IntegerRedisResponse(v); | ||
} | ||
} | ||
|
||
public IntegerRedisResponse(long value) { | ||
this.value = value; | ||
} | ||
|
||
// @Override | ||
// public Long data() { | ||
// return value; | ||
// } | ||
|
||
@Override | ||
public void encode(ByteBuf os) { | ||
os.writeByte(MARKER); | ||
Codec.writeLong(os, value); | ||
os.writeBytes(CRLF); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return Long.toString(value); | ||
} | ||
|
||
@Override | ||
public void encodeInline(ByteBuf out) { | ||
encode(out); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
cloudata-keyvalue/src/main/java/com/cloudata/keyvalue/redis/PingCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.cloudata.keyvalue.redis; | ||
|
||
public class PingCommand implements RedisCommand { | ||
|
||
@Override | ||
public RedisResponse execute(RedisServer server, RedisRequest command) throws RedisException { | ||
return StatusRedisResponse.PONG; | ||
} | ||
|
||
} |
5 changes: 5 additions & 0 deletions
5
cloudata-keyvalue/src/main/java/com/cloudata/keyvalue/redis/RedisCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.cloudata.keyvalue.redis; | ||
|
||
interface RedisCommand { | ||
RedisResponse execute(RedisServer server, RedisRequest command) throws RedisException; | ||
} |
Oops, something went wrong.