1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.client5.http.impl.cache.memcached;
28
29 import java.io.IOException;
30 import java.net.InetSocketAddress;
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.Map;
34
35 import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer;
36 import org.apache.hc.client5.http.cache.ResourceIOException;
37 import org.apache.hc.client5.http.impl.cache.AbstractBinaryCacheStorage;
38 import org.apache.hc.client5.http.impl.cache.ByteArrayCacheEntrySerializer;
39 import org.apache.hc.client5.http.impl.cache.CacheConfig;
40 import org.apache.hc.core5.util.Args;
41
42 import net.spy.memcached.CASResponse;
43 import net.spy.memcached.CASValue;
44 import net.spy.memcached.MemcachedClient;
45 import net.spy.memcached.MemcachedClientIF;
46 import net.spy.memcached.OperationTimeoutException;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public class MemcachedHttpCacheStorage extends AbstractBinaryCacheStorage<CASValue<Object>> {
87
88 private final MemcachedClientIF client;
89 private final KeyHashingScheme keyHashingScheme;
90
91
92
93
94
95
96
97
98
99 public MemcachedHttpCacheStorage(final InetSocketAddress address) throws IOException {
100 this(new MemcachedClient(address));
101 }
102
103
104
105
106
107
108 public MemcachedHttpCacheStorage(final MemcachedClient cache) {
109 this(cache, CacheConfig.DEFAULT, ByteArrayCacheEntrySerializer.INSTANCE, SHA256KeyHashingScheme.INSTANCE);
110 }
111
112
113
114
115
116
117
118
119
120 public MemcachedHttpCacheStorage(final MemcachedClientIF cache) {
121 this(cache, CacheConfig.DEFAULT, ByteArrayCacheEntrySerializer.INSTANCE, SHA256KeyHashingScheme.INSTANCE);
122 }
123
124
125
126
127
128
129
130
131
132
133
134 public MemcachedHttpCacheStorage(
135 final MemcachedClient client,
136 final CacheConfig config,
137 final HttpCacheEntrySerializer<byte[]> serializer,
138 final KeyHashingScheme keyHashingScheme) {
139 this((MemcachedClientIF) client, config, serializer, keyHashingScheme);
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public MemcachedHttpCacheStorage(
155 final MemcachedClientIF client,
156 final CacheConfig config,
157 final HttpCacheEntrySerializer<byte[]> serializer,
158 final KeyHashingScheme keyHashingScheme) {
159 super((config != null ? config : CacheConfig.DEFAULT).getMaxUpdateRetries(),
160 serializer != null ? serializer : ByteArrayCacheEntrySerializer.INSTANCE);
161 this.client = Args.notNull(client, "Memcached client");
162 this.keyHashingScheme = keyHashingScheme;
163 }
164
165 @Override
166 protected String digestToStorageKey(final String key) {
167 return keyHashingScheme.hash(key);
168 }
169
170 @Override
171 protected void store(final String storageKey, final byte[] storageObject) throws ResourceIOException {
172 client.set(storageKey, 0, storageObject);
173 }
174
175 private byte[] castAsByteArray(final Object storageObject) throws ResourceIOException {
176 if (storageObject == null) {
177 return null;
178 }
179 if (storageObject instanceof byte[]) {
180 return (byte[]) storageObject;
181 }
182 throw new ResourceIOException("Unexpected cache content: " + storageObject.getClass());
183 }
184
185 @Override
186 protected byte[] restore(final String storageKey) throws ResourceIOException {
187 try {
188 return castAsByteArray(client.get(storageKey));
189 } catch (final OperationTimeoutException ex) {
190 throw new MemcachedOperationTimeoutException(ex);
191 }
192 }
193
194 @Override
195 protected CASValue<Object> getForUpdateCAS(final String storageKey) throws ResourceIOException {
196 try {
197 return client.gets(storageKey);
198 } catch (final OperationTimeoutException ex) {
199 throw new MemcachedOperationTimeoutException(ex);
200 }
201 }
202
203 @Override
204 protected byte[] getStorageObject(final CASValue<Object> casValue) throws ResourceIOException {
205 return castAsByteArray(casValue.getValue());
206 }
207
208 @Override
209 protected boolean updateCAS(
210 final String storageKey, final CASValue<Object> casValue, final byte[] storageObject) throws ResourceIOException {
211 try {
212 final CASResponse casResult = client.cas(storageKey, casValue.getCas(), storageObject);
213 return casResult == CASResponse.OK;
214 } catch (final OperationTimeoutException ex) {
215 throw new MemcachedOperationTimeoutException(ex);
216 }
217 }
218
219 @Override
220 protected void delete(final String storageKey) throws ResourceIOException {
221 client.delete(storageKey);
222 }
223
224 @Override
225 protected Map<String, byte[]> bulkRestore(final Collection<String> storageKeys) throws ResourceIOException {
226 try {
227 final Map<String, ?> storageObjectMap = client.getBulk(storageKeys);
228 final Map<String, byte[]> resultMap = new HashMap<>(storageObjectMap.size());
229 for (final Map.Entry<String, ?> resultEntry: storageObjectMap.entrySet()) {
230 resultMap.put(resultEntry.getKey(), castAsByteArray(resultEntry.getValue()));
231 }
232 return resultMap;
233 } catch (final OperationTimeoutException ex) {
234 throw new MemcachedOperationTimeoutException(ex);
235 }
236 }
237
238 }