Skip to content

Commit

Permalink
Realign with Netty Redis codec. (Azure#391)
Browse files Browse the repository at this point in the history
  • Loading branch information
StormHub authored and nayato committed Apr 13, 2018
1 parent f227f95 commit b8370d7
Show file tree
Hide file tree
Showing 38 changed files with 972 additions and 1,267 deletions.
1 change: 1 addition & 0 deletions src/DotNetty.Buffers/AbstractReferenceCountedByteBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace DotNetty.Buffers
using System.Diagnostics.Contracts;
using System.Threading;
using DotNetty.Common;
using DotNetty.Common.Utilities;

public abstract class AbstractReferenceCountedByteBuffer : AbstractByteBuffer
{
Expand Down
2 changes: 1 addition & 1 deletion src/DotNetty.Buffers/ByteBufferUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ internal static int WriteUtf8(AbstractByteBuffer buffer, int writerIndex, string

internal static int Utf8MaxBytes(ICharSequence seq) => Utf8MaxBytes(seq.Count);

internal static int Utf8MaxBytes(string seq) => Utf8MaxBytes(seq.Length);
public static int Utf8MaxBytes(string seq) => Utf8MaxBytes(seq.Length);

internal static int Utf8MaxBytes(int seqLength) => seqLength * MaxBytesPerCharUtf8;

Expand Down
1 change: 1 addition & 0 deletions src/DotNetty.Buffers/DefaultByteBufferHolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace DotNetty.Buffers
{
using System.Diagnostics.Contracts;
using DotNetty.Common;
using DotNetty.Common.Utilities;

public class DefaultByteBufferHolder : IByteBufferHolder
{
Expand Down
1 change: 1 addition & 0 deletions src/DotNetty.Buffers/ThrowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace DotNetty.Buffers
{
using System;
using System.Runtime.CompilerServices;
using DotNetty.Common.Utilities;

static class ThrowHelper
{
Expand Down
1 change: 1 addition & 0 deletions src/DotNetty.Codecs.Http/DefaultFullHttpRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace DotNetty.Codecs.Http
using System.Text;
using DotNetty.Buffers;
using DotNetty.Common;
using DotNetty.Common.Utilities;

public class DefaultFullHttpRequest : DefaultHttpRequest, IFullHttpRequest
{
Expand Down
1 change: 1 addition & 0 deletions src/DotNetty.Codecs.Http/DefaultFullHttpResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace DotNetty.Codecs.Http
using System.Text;
using DotNetty.Buffers;
using DotNetty.Common;
using DotNetty.Common.Utilities;

public class DefaultFullHttpResponse : DefaultHttpResponse, IFullHttpResponse
{
Expand Down
132 changes: 59 additions & 73 deletions src/DotNetty.Codecs.Redis/FixedRedisMessagePool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,20 @@
namespace DotNetty.Codecs.Redis
{
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using DotNetty.Buffers;
using DotNetty.Codecs.Redis.Messages;

public sealed class FixedRedisMessagePool : IRedisMessagePool
{
readonly IReadOnlyDictionary<string, SimpleStringRedisMessage> stringToSimpleStringMessages;
readonly IReadOnlyDictionary<IByteBuffer, SimpleStringRedisMessage> byteBufferToSimpleStringMessages;

readonly IReadOnlyDictionary<string, ErrorRedisMessage> stringToErrorMessages;
readonly IReadOnlyDictionary<IByteBuffer, ErrorRedisMessage> byteBufferToErrorMessages;

readonly IReadOnlyDictionary<long, IntegerRedisMessage> longToIntegerMessages;
readonly IReadOnlyDictionary<long, byte[]> longToBytes;
readonly IReadOnlyDictionary<IByteBuffer, IntegerRedisMessage> byteBufferToIntegerMessages;

static readonly FixedRedisMessagePool Instance;

static FixedRedisMessagePool()
{
Instance = new FixedRedisMessagePool();
}

public static IRedisMessagePool Default => Instance;

static readonly string[] SimpleStrings =
static readonly string[] DefaultSimpleStrings =
{
"OK",
"PONG",
"QUEUED"
};

static readonly string[] Errors =
static readonly string[] DefaultErrors =
{
"ERR",
"ERR index out of range",
Expand All @@ -49,9 +29,9 @@ static FixedRedisMessagePool()
"EXECABORT Transaction discarded because of previous errors.",
"LOADING Redis is loading the dataset in memory",
"MASTERDOWN Link with MASTER is down and slave-serve-stale-data is set to 'no'.",
"MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. "
+ "Commands that may modify the data set are disabled. Please check Redis logs for details "
+ "about the error.",
"MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. " +
"Commands that may modify the data set are disabled. Please check Redis logs for details " +
"about the error.",
"NOAUTH Authentication required.",
"NOREPLICAS Not enough good slaves to write.",
"NOSCRIPT No matching script. Please use EVAL.",
Expand All @@ -60,80 +40,86 @@ static FixedRedisMessagePool()
"WRONGTYPE Operation against a key holding the wrong kind of value"
};

static readonly long MinimumCachedIntegerNumber = RedisConstants.NullValue; // inclusive
const long MaximumCachedIntegerNumber = 128; // exclusive

// cached integer size cannot larger than `int` range because of Collection.
static readonly int SizeCachedIntegerNumber = (int)(MaximumCachedIntegerNumber - MinimumCachedIntegerNumber);

public static readonly FixedRedisMessagePool Instance = new FixedRedisMessagePool();

// internal caches.
readonly Dictionary<IByteBuffer, SimpleStringRedisMessage> byteBufToSimpleStrings;
readonly Dictionary<string, SimpleStringRedisMessage> stringToSimpleStrings;
readonly Dictionary<IByteBuffer, ErrorRedisMessage> byteBufToErrors;
readonly Dictionary<string, ErrorRedisMessage> stringToErrors;
readonly Dictionary<IByteBuffer, IntegerRedisMessage> byteBufToIntegers;
readonly Dictionary<long, IntegerRedisMessage> longToIntegers;
readonly Dictionary<long, byte[]> longToByteBufs;

FixedRedisMessagePool()
{
var stringToSimpleStringValues = new Dictionary<string, SimpleStringRedisMessage>();
var byteBufferToSimpleStringValues = new Dictionary<IByteBuffer, SimpleStringRedisMessage>();
this.byteBufToSimpleStrings = new Dictionary<IByteBuffer, SimpleStringRedisMessage>(DefaultSimpleStrings.Length);
this.stringToSimpleStrings = new Dictionary<string, SimpleStringRedisMessage>(DefaultSimpleStrings.Length);

foreach (string simpleString in SimpleStrings)
foreach (string simpleString in DefaultSimpleStrings)
{
IByteBuffer key = Unpooled.UnreleasableBuffer(
Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(simpleString)));

var redisMessage = new SimpleStringRedisMessage(simpleString);
stringToSimpleStringValues.Add(simpleString, redisMessage);
byteBufferToSimpleStringValues.Add(key, redisMessage);
var cached = new SimpleStringRedisMessage(simpleString);
this.byteBufToSimpleStrings.Add(key, cached);
this.stringToSimpleStrings.Add(simpleString, cached);
}
this.stringToSimpleStringMessages = new ReadOnlyDictionary<string, SimpleStringRedisMessage>(stringToSimpleStringValues);
this.byteBufferToSimpleStringMessages = new ReadOnlyDictionary<IByteBuffer, SimpleStringRedisMessage>(byteBufferToSimpleStringValues);

var errorToErrorValues = new Dictionary<string, ErrorRedisMessage>();
var byteBufferToErrorValues = new Dictionary<IByteBuffer, ErrorRedisMessage>();
foreach (string error in Errors)
this.byteBufToErrors = new Dictionary<IByteBuffer, ErrorRedisMessage>(DefaultErrors.Length);
this.stringToErrors = new Dictionary<string, ErrorRedisMessage>(DefaultErrors.Length);
foreach (string error in DefaultErrors)
{
IByteBuffer key = Unpooled.UnreleasableBuffer(
Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(error)));

var redisMessage = new ErrorRedisMessage(error);
errorToErrorValues.Add(error, redisMessage);
byteBufferToErrorValues.Add(key, redisMessage);
var cached = new ErrorRedisMessage(error);
this.byteBufToErrors.Add(key, cached);
this.stringToErrors.Add(error, cached);
}
this.stringToErrorMessages = new ReadOnlyDictionary<string, ErrorRedisMessage>(errorToErrorValues);
this.byteBufferToErrorMessages = new ReadOnlyDictionary<IByteBuffer, ErrorRedisMessage>(byteBufferToErrorValues);

var longToIntegerValues = new Dictionary<long, IntegerRedisMessage>();
var longToByteBufferValues = new Dictionary<long, byte[]>();
var byteBufferToIntegerValues = new Dictionary<IByteBuffer, IntegerRedisMessage>();
this.byteBufToIntegers = new Dictionary<IByteBuffer, IntegerRedisMessage>();
this.longToIntegers = new Dictionary<long, IntegerRedisMessage>(SizeCachedIntegerNumber);
this.longToByteBufs = new Dictionary<long, byte[]>(SizeCachedIntegerNumber);

for (long value = MinimumCachedIntegerNumber; value < MaximumCachedIntegerNumber; value++)
{
byte[] bytes = RedisCodecUtil.LongToAsciiBytes(value);
IByteBuffer key = Unpooled.UnreleasableBuffer(
Unpooled.WrappedBuffer(bytes));

var redisMessage = new IntegerRedisMessage(value);
longToIntegerValues.Add(value, redisMessage);
longToByteBufferValues.Add(value, bytes);
byteBufferToIntegerValues.Add(key, redisMessage);
byte[] keyBytes = RedisCodecUtil.LongToAsciiBytes(value);
IByteBuffer keyByteBuf = Unpooled.UnreleasableBuffer(
Unpooled.WrappedBuffer(keyBytes));

var cached = new IntegerRedisMessage(value);
this.byteBufToIntegers.Add(keyByteBuf, cached);
this.longToIntegers.Add(value, cached);
this.longToByteBufs.Add(value, keyBytes);
}

this.longToIntegerMessages = new ReadOnlyDictionary<long, IntegerRedisMessage>(longToIntegerValues);
this.longToBytes = new ReadOnlyDictionary<long, byte[]>(longToByteBufferValues);
this.byteBufferToIntegerMessages = new ReadOnlyDictionary<IByteBuffer, IntegerRedisMessage>(byteBufferToIntegerValues);
}

static readonly long MinimumCachedIntegerNumber = RedisConstants.NullValue; // inclusive
const long MaximumCachedIntegerNumber = 128; // exclusive

public bool TryGetMessage(string content, out SimpleStringRedisMessage message)
=> this.stringToSimpleStringMessages.TryGetValue(content, out message);
public bool TryGetSimpleString(string content, out SimpleStringRedisMessage message)
=> this.stringToSimpleStrings.TryGetValue(content, out message);

public bool TryGetMessage(IByteBuffer content, out SimpleStringRedisMessage message)
=> this.byteBufferToSimpleStringMessages.TryGetValue(content, out message);
public bool TryGetSimpleString(IByteBuffer content, out SimpleStringRedisMessage message)
=> this.byteBufToSimpleStrings.TryGetValue(content, out message);

public bool TryGetMessage(string content, out ErrorRedisMessage message)
=> this.stringToErrorMessages.TryGetValue(content, out message);
public bool TryGetError(string content, out ErrorRedisMessage message)
=> this.stringToErrors.TryGetValue(content, out message);

public bool TryGetMessage(IByteBuffer content, out ErrorRedisMessage message)
=> this.byteBufferToErrorMessages.TryGetValue(content, out message);
public bool TryGetError(IByteBuffer content, out ErrorRedisMessage message)
=> this.byteBufToErrors.TryGetValue(content, out message);

public bool TryGetMessage(long value, out IntegerRedisMessage message)
=> this.longToIntegerMessages.TryGetValue(value, out message);
public bool TryGetInteger(long value, out IntegerRedisMessage message)
=> this.longToIntegers.TryGetValue(value, out message);

public bool TryGetMessage(IByteBuffer content, out IntegerRedisMessage message)
=> this.byteBufferToIntegerMessages.TryGetValue(content, out message);
public bool TryGetInteger(IByteBuffer content, out IntegerRedisMessage message)
=> this.byteBufToIntegers.TryGetValue(content, out message);

public bool TryGetBytes(long value, out byte[] bytes)
=> this.longToBytes.TryGetValue(value, out bytes);
public bool TryGetByteBufferOfInteger(long value, out byte[] bytes)
=> this.longToByteBufs.TryGetValue(value, out bytes);
}
}
14 changes: 7 additions & 7 deletions src/DotNetty.Codecs.Redis/IRedisMessagePool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ namespace DotNetty.Codecs.Redis

public interface IRedisMessagePool
{
bool TryGetMessage(string content, out SimpleStringRedisMessage message);
bool TryGetSimpleString(string content, out SimpleStringRedisMessage message);

bool TryGetMessage(IByteBuffer content, out SimpleStringRedisMessage message);
bool TryGetSimpleString(IByteBuffer content, out SimpleStringRedisMessage message);

bool TryGetMessage(string content, out ErrorRedisMessage message);
bool TryGetError(string content, out ErrorRedisMessage message);

bool TryGetMessage(IByteBuffer content, out ErrorRedisMessage message);
bool TryGetError(IByteBuffer content, out ErrorRedisMessage message);

bool TryGetMessage(IByteBuffer content, out IntegerRedisMessage message);
bool TryGetInteger(IByteBuffer content, out IntegerRedisMessage message);

bool TryGetMessage(long value, out IntegerRedisMessage message);
bool TryGetInteger(long value, out IntegerRedisMessage message);

bool TryGetBytes(long value, out byte[] bytes);
bool TryGetByteBufferOfInteger(long value, out byte[] bytes);
}
}
29 changes: 0 additions & 29 deletions src/DotNetty.Codecs.Redis/MessageAggregationException.cs

This file was deleted.

10 changes: 10 additions & 0 deletions src/DotNetty.Codecs.Redis/Messages/AbstractStringRedisMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
namespace DotNetty.Codecs.Redis.Messages
{
using System.Diagnostics.Contracts;
using System.Text;
using DotNetty.Common.Utilities;

public abstract class AbstractStringRedisMessage : IRedisMessage
{
Expand All @@ -15,5 +17,13 @@ protected AbstractStringRedisMessage(string content)
}

public string Content { get; }

public override string ToString() =>
new StringBuilder(StringUtil.SimpleClassName(this))
.Append('[')
.Append("content=")
.Append(this.Content)
.Append(']')
.ToString();
}
}
19 changes: 14 additions & 5 deletions src/DotNetty.Codecs.Redis/Messages/ArrayHeaderRedisMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,30 @@

namespace DotNetty.Codecs.Redis.Messages
{
using System.Diagnostics.Contracts;
using System.Text;
using DotNetty.Common.Utilities;

public sealed class ArrayHeaderRedisMessage : IRedisMessage
public class ArrayHeaderRedisMessage : IRedisMessage
{
public ArrayHeaderRedisMessage(long length)
{
Contract.Requires(length >= RedisConstants.NullValue);

if (length < RedisConstants.NullValue)
{
throw new RedisCodecException($"length: {length} (expected: >= {RedisConstants.NullValue})");
}
this.Length = length;
}

public long Length { get; }

public bool IsNull => this.Length == RedisConstants.NullValue;

public override string ToString() => $"{nameof(ArrayHeaderRedisMessage)}[length={this.Length}]";
public override string ToString() =>
new StringBuilder(StringUtil.SimpleClassName(this))
.Append('[')
.Append("length=")
.Append(this.Length)
.Append(']')
.ToString();
}
}
Loading

0 comments on commit b8370d7

Please sign in to comment.