1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.redis;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.Unpooled;
20 import io.netty.util.CharsetUtil;
21 import io.netty.util.collection.LongObjectHashMap;
22 import io.netty.util.collection.LongObjectMap;
23 import io.netty.util.internal.UnstableApi;
24
25 import java.util.HashMap;
26 import java.util.Map;
27
28
29
30
31 @UnstableApi
32 public final class FixedRedisMessagePool implements RedisMessagePool {
33
34 public enum RedisReplyKey {
35 OK, PONG, QUEUED
36 }
37
38 public enum RedisErrorKey {
39 ERR("ERR"),
40 ERR_IDX("ERR index out of range"),
41 ERR_NOKEY("ERR no such key"),
42 ERR_SAMEOBJ("ERR source and destination objects are the same"),
43 ERR_SYNTAX("ERR syntax error"),
44 BUSY("BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE."),
45 BUSYKEY("BUSYKEY Target key name already exists."),
46 EXECABORT("EXECABORT Transaction discarded because of previous errors."),
47 LOADING("LOADING Redis is loading the dataset in memory"),
48 MASTERDOWN("MASTERDOWN Link with MASTER is down and slave-serve-stale-data is set to 'no'."),
49 MISCONF("MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. " +
50 "Commands that may modify the data set are disabled. Please check Redis logs for details " +
51 "about the error."),
52 NOREPLICAS("NOREPLICAS Not enough good slaves to write."),
53 NOSCRIPT("NOSCRIPT No matching script. Please use EVAL."),
54 OOM("OOM command not allowed when used memory > 'maxmemory'."),
55 READONLY("READONLY You can't write against a read only slave."),
56 WRONGTYPE("WRONGTYPE Operation against a key holding the wrong kind of value"),
57 NOT_AUTH("NOAUTH Authentication required.");
58
59 private final String msg;
60
61 RedisErrorKey(String msg) {
62 this.msg = msg;
63 }
64
65 @Override
66 public String toString() {
67 return msg;
68 }
69 }
70
71 private static final long MIN_CACHED_INTEGER_NUMBER = RedisConstants.NULL_VALUE;
72 private static final long MAX_CACHED_INTEGER_NUMBER = 128;
73
74
75 private static final int SIZE_CACHED_INTEGER_NUMBER = (int) (MAX_CACHED_INTEGER_NUMBER - MIN_CACHED_INTEGER_NUMBER);
76
77
78
79
80 public static final FixedRedisMessagePool INSTANCE = new FixedRedisMessagePool();
81
82
83 private final Map<ByteBuf, SimpleStringRedisMessage> byteBufToSimpleStrings;
84 private final Map<String, SimpleStringRedisMessage> stringToSimpleStrings;
85 private final Map<RedisReplyKey, SimpleStringRedisMessage> keyToSimpleStrings;
86 private final Map<ByteBuf, ErrorRedisMessage> byteBufToErrors;
87 private final Map<String, ErrorRedisMessage> stringToErrors;
88 private final Map<RedisErrorKey, ErrorRedisMessage> keyToErrors;
89 private final Map<ByteBuf, IntegerRedisMessage> byteBufToIntegers;
90 private final LongObjectMap<IntegerRedisMessage> longToIntegers;
91 private final LongObjectMap<byte[]> longToByteBufs;
92
93
94
95
96 private FixedRedisMessagePool() {
97 keyToSimpleStrings = new HashMap<RedisReplyKey, SimpleStringRedisMessage>(RedisReplyKey.values().length, 1.0f);
98 stringToSimpleStrings = new HashMap<String, SimpleStringRedisMessage>(RedisReplyKey.values().length, 1.0f);
99 byteBufToSimpleStrings = new HashMap<ByteBuf, SimpleStringRedisMessage>(RedisReplyKey.values().length, 1.0f);
100 for (RedisReplyKey value : RedisReplyKey.values()) {
101 ByteBuf key = Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(
102 value.name().getBytes(CharsetUtil.UTF_8))).asReadOnly();
103 SimpleStringRedisMessage message = new SimpleStringRedisMessage(new String(Unpooled.unreleasableBuffer(
104 Unpooled.wrappedBuffer(value.name().getBytes(CharsetUtil.UTF_8))).array()));
105 stringToSimpleStrings.put(value.name(), message);
106 keyToSimpleStrings.put(value, message);
107 byteBufToSimpleStrings.put(key, message);
108 }
109
110 keyToErrors = new HashMap<RedisErrorKey, ErrorRedisMessage>(RedisErrorKey.values().length, 1.0f);
111 stringToErrors = new HashMap<String, ErrorRedisMessage>(RedisErrorKey.values().length, 1.0f);
112 byteBufToErrors = new HashMap<ByteBuf, ErrorRedisMessage>(RedisErrorKey.values().length, 1.0f);
113 for (RedisErrorKey value : RedisErrorKey.values()) {
114 ByteBuf key = Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(
115 value.toString().getBytes(CharsetUtil.UTF_8))).asReadOnly();
116 ErrorRedisMessage message = new ErrorRedisMessage(new String(Unpooled.unreleasableBuffer(
117 Unpooled.wrappedBuffer(value.toString().getBytes(CharsetUtil.UTF_8))).array()));
118 stringToErrors.put(value.toString(), message);
119 keyToErrors.put(value, message);
120 byteBufToErrors.put(key, message);
121 }
122
123 byteBufToIntegers = new HashMap<ByteBuf, IntegerRedisMessage>(SIZE_CACHED_INTEGER_NUMBER, 1.0f);
124 longToIntegers = new LongObjectHashMap<IntegerRedisMessage>(SIZE_CACHED_INTEGER_NUMBER, 1.0f);
125 longToByteBufs = new LongObjectHashMap<byte[]>(SIZE_CACHED_INTEGER_NUMBER, 1.0f);
126 for (long value = MIN_CACHED_INTEGER_NUMBER; value < MAX_CACHED_INTEGER_NUMBER; value++) {
127 byte[] keyBytes = RedisCodecUtil.longToAsciiBytes(value);
128 ByteBuf keyByteBuf = Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(keyBytes)).asReadOnly();
129 IntegerRedisMessage cached = new IntegerRedisMessage(value);
130 byteBufToIntegers.put(keyByteBuf, cached);
131 longToIntegers.put(value, cached);
132 longToByteBufs.put(value, keyBytes);
133 }
134 }
135
136 @Override
137 public SimpleStringRedisMessage getSimpleString(String content) {
138 return stringToSimpleStrings.get(content);
139 }
140
141
142
143
144
145 public SimpleStringRedisMessage getSimpleString(RedisReplyKey key) {
146 return keyToSimpleStrings.get(key);
147 }
148
149 @Override
150 public SimpleStringRedisMessage getSimpleString(ByteBuf content) {
151 return byteBufToSimpleStrings.get(content);
152 }
153
154 @Override
155 public ErrorRedisMessage getError(String content) {
156 return stringToErrors.get(content);
157 }
158
159
160
161
162
163 public ErrorRedisMessage getError(RedisErrorKey key) {
164 return keyToErrors.get(key);
165 }
166
167 @Override
168 public ErrorRedisMessage getError(ByteBuf content) {
169 return byteBufToErrors.get(content);
170 }
171
172 @Override
173 public IntegerRedisMessage getInteger(long value) {
174 return longToIntegers.get(value);
175 }
176
177 @Override
178 public IntegerRedisMessage getInteger(ByteBuf content) {
179 return byteBufToIntegers.get(content);
180 }
181
182 @Override
183 public byte[] getByteBufOfInteger(long value) {
184 return longToByteBufs.get(value);
185 }
186 }