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 import java.util.concurrent.CancellationException;
35
36 import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer;
37 import org.apache.hc.client5.http.cache.ResourceIOException;
38 import org.apache.hc.client5.http.impl.cache.AbstractBinaryCacheStorage;
39 import org.apache.hc.client5.http.impl.cache.CacheConfig;
40 import org.apache.hc.client5.http.impl.cache.HttpByteArrayCacheEntrySerializer;
41 import org.apache.hc.core5.util.Args;
42
43 import net.spy.memcached.CASResponse;
44 import net.spy.memcached.CASValue;
45 import net.spy.memcached.MemcachedClient;
46 import net.spy.memcached.MemcachedClientIF;
47 import net.spy.memcached.OperationTimeoutException;
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
87 public class MemcachedHttpCacheStorage extends AbstractBinaryCacheStorage<CASValue<Object>> {
88
89 private final MemcachedClientIF client;
90 private final KeyHashingScheme keyHashingScheme;
91
92
93
94
95
96
97
98
99
100 public MemcachedHttpCacheStorage(final InetSocketAddress address) throws IOException {
101 this(new MemcachedClient(address));
102 }
103
104
105
106
107
108
109 public MemcachedHttpCacheStorage(final MemcachedClient cache) {
110 this(cache, CacheConfig.DEFAULT, HttpByteArrayCacheEntrySerializer.INSTANCE, SHA256KeyHashingScheme.INSTANCE);
111 }
112
113
114
115
116
117
118
119
120
121 public MemcachedHttpCacheStorage(final MemcachedClientIF cache) {
122 this(cache, CacheConfig.DEFAULT, HttpByteArrayCacheEntrySerializer.INSTANCE, SHA256KeyHashingScheme.INSTANCE);
123 }
124
125
126
127
128
129
130
131
132
133
134
135 public MemcachedHttpCacheStorage(
136 final MemcachedClient client,
137 final CacheConfig config,
138 final HttpCacheEntrySerializer<byte[]> serializer,
139 final KeyHashingScheme keyHashingScheme) {
140 this((MemcachedClientIF) client, config, serializer, keyHashingScheme);
141 }
142
143
144
145
146
147
148
149
150
151
152
153
154
155 public MemcachedHttpCacheStorage(
156 final MemcachedClientIF client,
157 final CacheConfig config,
158 final HttpCacheEntrySerializer<byte[]> serializer,
159 final KeyHashingScheme keyHashingScheme) {
160 super((config != null ? config : CacheConfig.DEFAULT).getMaxUpdateRetries(),
161 serializer != null ? serializer : HttpByteArrayCacheEntrySerializer.INSTANCE);
162 this.client = Args.notNull(client, "Memcached client");
163 this.keyHashingScheme = keyHashingScheme;
164 }
165
166 @Override
167 protected String digestToStorageKey(final String key) {
168 return keyHashingScheme.hash(key);
169 }
170
171 @Override
172 protected void store(final String storageKey, final byte[] storageObject) throws ResourceIOException {
173 try {
174 client.set(storageKey, 0, storageObject);
175 } catch (final CancellationException ex) {
176 throw new MemcachedOperationCancellationException(ex);
177 }
178 }
179
180 private byte[] castAsByteArray(final Object storageObject) throws ResourceIOException {
181 if (storageObject == null) {
182 return null;
183 }
184 if (storageObject instanceof byte[]) {
185 return (byte[]) storageObject;
186 }
187 throw new ResourceIOException("Unexpected cache content: " + storageObject.getClass());
188 }
189
190 @Override
191 protected byte[] restore(final String storageKey) throws ResourceIOException {
192 try {
193 return castAsByteArray(client.get(storageKey));
194 } catch (final CancellationException ex) {
195 throw new MemcachedOperationCancellationException(ex);
196 } catch (final OperationTimeoutException ex) {
197 throw new MemcachedOperationTimeoutException(ex);
198 }
199 }
200
201 @Override
202 protected CASValue<Object> getForUpdateCAS(final String storageKey) throws ResourceIOException {
203 try {
204 return client.gets(storageKey);
205 } catch (final CancellationException ex) {
206 throw new MemcachedOperationCancellationException(ex);
207 } catch (final OperationTimeoutException ex) {
208 throw new MemcachedOperationTimeoutException(ex);
209 }
210 }
211
212 @Override
213 protected byte[] getStorageObject(final CASValue<Object> casValue) throws ResourceIOException {
214 return castAsByteArray(casValue.getValue());
215 }
216
217 @Override
218 protected boolean updateCAS(
219 final String storageKey, final CASValue<Object> casValue, final byte[] storageObject) throws ResourceIOException {
220 try {
221 final CASResponse casResult = client.cas(storageKey, casValue.getCas(), storageObject);
222 return casResult == CASResponse.OK;
223 } catch (final CancellationException ex) {
224 throw new MemcachedOperationCancellationException(ex);
225 } catch (final OperationTimeoutException ex) {
226 throw new MemcachedOperationTimeoutException(ex);
227 }
228 }
229
230 @Override
231 protected void delete(final String storageKey) throws ResourceIOException {
232 try {
233 client.delete(storageKey);
234 } catch (final CancellationException ex) {
235 throw new MemcachedOperationCancellationException(ex);
236 }
237 }
238
239 @Override
240 protected Map<String, byte[]> bulkRestore(final Collection<String> storageKeys) throws ResourceIOException {
241 try {
242 final Map<String, ?> storageObjectMap = client.getBulk(storageKeys);
243 final Map<String, byte[]> resultMap = new HashMap<>(storageObjectMap.size());
244 for (final Map.Entry<String, ?> resultEntry: storageObjectMap.entrySet()) {
245 resultMap.put(resultEntry.getKey(), castAsByteArray(resultEntry.getValue()));
246 }
247 return resultMap;
248 } catch (final CancellationException ex) {
249 throw new MemcachedOperationCancellationException(ex);
250 } catch (final OperationTimeoutException ex) {
251 throw new MemcachedOperationTimeoutException(ex);
252 }
253 }
254
255 }