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.OperationTimeoutException;
46
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 public class MemcachedHttpCacheStorage extends AbstractBinaryCacheStorage<CASValue<Object>> {
86
87 private final MemcachedClient client;
88 private final KeyHashingScheme keyHashingScheme;
89
90
91
92
93
94
95
96
97
98 public MemcachedHttpCacheStorage(final InetSocketAddress address) throws IOException {
99 this(new MemcachedClient(address));
100 }
101
102
103
104
105
106
107 public MemcachedHttpCacheStorage(final MemcachedClient cache) {
108 this(cache, CacheConfig.DEFAULT, ByteArrayCacheEntrySerializer.INSTANCE, SHA256KeyHashingScheme.INSTANCE);
109 }
110
111
112
113
114
115
116
117
118
119
120
121 public MemcachedHttpCacheStorage(
122 final MemcachedClient client,
123 final CacheConfig config,
124 final HttpCacheEntrySerializer<byte[]> serializer,
125 final KeyHashingScheme keyHashingScheme) {
126 super((config != null ? config : CacheConfig.DEFAULT).getMaxUpdateRetries(),
127 serializer != null ? serializer : ByteArrayCacheEntrySerializer.INSTANCE);
128 this.client = Args.notNull(client, "Memcached client");
129 this.keyHashingScheme = keyHashingScheme;
130 }
131
132 @Override
133 protected String digestToStorageKey(final String key) {
134 return keyHashingScheme.hash(key);
135 }
136
137 @Override
138 protected void store(final String storageKey, final byte[] storageObject) throws ResourceIOException {
139 client.set(storageKey, 0, storageObject);
140 }
141
142 private byte[] castAsByteArray(final Object storageObject) throws ResourceIOException {
143 if (storageObject == null) {
144 return null;
145 }
146 if (storageObject instanceof byte[]) {
147 return (byte[]) storageObject;
148 }
149 throw new ResourceIOException("Unexpected cache content: " + storageObject.getClass());
150 }
151
152 @Override
153 protected byte[] restore(final String storageKey) throws ResourceIOException {
154 try {
155 return castAsByteArray(client.get(storageKey));
156 } catch (final OperationTimeoutException ex) {
157 throw new MemcachedOperationTimeoutException(ex);
158 }
159 }
160
161 @Override
162 protected CASValue<Object> getForUpdateCAS(final String storageKey) throws ResourceIOException {
163 try {
164 return client.gets(storageKey);
165 } catch (final OperationTimeoutException ex) {
166 throw new MemcachedOperationTimeoutException(ex);
167 }
168 }
169
170 @Override
171 protected byte[] getStorageObject(final CASValue<Object> casValue) throws ResourceIOException {
172 return castAsByteArray(casValue.getValue());
173 }
174
175 @Override
176 protected boolean updateCAS(
177 final String storageKey, final CASValue<Object> casValue, final byte[] storageObject) throws ResourceIOException {
178 final CASResponse casResult = client.cas(storageKey, casValue.getCas(), storageObject);
179 return casResult == CASResponse.OK;
180 }
181
182 @Override
183 protected void delete(final String storageKey) throws ResourceIOException {
184 client.delete(storageKey);
185 }
186
187 @Override
188 protected Map<String, byte[]> bulkRestore(final Collection<String> storageKeys) throws ResourceIOException {
189 final Map<String, ?> storageObjectMap = client.getBulk(storageKeys);
190 final Map<String, byte[]> resultMap = new HashMap<>(storageObjectMap.size());
191 for (final Map.Entry<String, ?> resultEntry: storageObjectMap.entrySet()) {
192 resultMap.put(resultEntry.getKey(), castAsByteArray(resultEntry.getValue()));
193 }
194 return resultMap;
195 }
196
197 }