...
|
...
|
@@ -26,9 +26,7 @@ import org.eclipse.leshan.core.util.NamedThreadFactory; |
26
|
26
|
import org.eclipse.leshan.core.util.Validate;
|
27
|
27
|
import org.eclipse.leshan.server.californium.observation.ObserveUtil;
|
28
|
28
|
import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
|
29
|
|
-import org.eclipse.leshan.server.redis.JedisLock;
|
30
|
29
|
import org.eclipse.leshan.server.redis.RedisRegistrationStore;
|
31
|
|
-import org.eclipse.leshan.server.redis.SingleInstanceJedisLock;
|
32
|
30
|
import org.eclipse.leshan.server.redis.serialization.ObservationSerDes;
|
33
|
31
|
import org.eclipse.leshan.server.redis.serialization.RegistrationSerDes;
|
34
|
32
|
import org.eclipse.leshan.server.registration.Deregistration;
|
...
|
...
|
@@ -38,11 +36,12 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; |
38
|
36
|
import org.eclipse.leshan.server.registration.UpdatedRegistration;
|
39
|
37
|
import org.slf4j.Logger;
|
40
|
38
|
import org.slf4j.LoggerFactory;
|
|
39
|
+import org.springframework.data.redis.connection.RedisClusterConnection;
|
|
40
|
+import org.springframework.data.redis.connection.RedisConnection;
|
41
|
41
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
42
|
|
-import redis.clients.jedis.Jedis;
|
43
|
|
-import redis.clients.jedis.ScanParams;
|
44
|
|
-import redis.clients.jedis.ScanResult;
|
45
|
|
-import redis.clients.jedis.Transaction;
|
|
42
|
+import org.springframework.data.redis.core.Cursor;
|
|
43
|
+import org.springframework.data.redis.core.ScanOptions;
|
|
44
|
+import org.springframework.integration.redis.util.RedisLockRegistry;
|
46
|
45
|
|
47
|
46
|
import java.net.InetSocketAddress;
|
48
|
47
|
import java.util.ArrayList;
|
...
|
...
|
@@ -50,13 +49,14 @@ import java.util.Arrays; |
50
|
49
|
import java.util.Collection;
|
51
|
50
|
import java.util.Collections;
|
52
|
51
|
import java.util.Iterator;
|
|
52
|
+import java.util.LinkedList;
|
53
|
53
|
import java.util.List;
|
54
|
|
-import java.util.NoSuchElementException;
|
55
|
54
|
import java.util.Set;
|
56
|
55
|
import java.util.concurrent.Executors;
|
57
|
56
|
import java.util.concurrent.ScheduledExecutorService;
|
58
|
57
|
import java.util.concurrent.ScheduledFuture;
|
59
|
58
|
import java.util.concurrent.TimeUnit;
|
|
59
|
+import java.util.concurrent.locks.Lock;
|
60
|
60
|
|
61
|
61
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
62
|
62
|
|
...
|
...
|
@@ -92,7 +92,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
92
|
92
|
private final int cleanLimit; // maximum number to clean in a clean period
|
93
|
93
|
private final long gracePeriod; // in seconds
|
94
|
94
|
|
95
|
|
- private final JedisLock lock;
|
|
95
|
+ private final RedisLockRegistry redisLock;
|
96
|
96
|
|
97
|
97
|
public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory) {
|
98
|
98
|
this(connectionFactory, DEFAULT_CLEAN_PERIOD, DEFAULT_GRACE_PERIOD, DEFAULT_CLEAN_LIMIT); // default clean period 60s
|
...
|
...
|
@@ -106,20 +106,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
106
|
106
|
|
107
|
107
|
public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec,
|
108
|
108
|
long lifetimeGracePeriodInSec, int cleanLimit) {
|
109
|
|
- this(connectionFactory, schedExecutor, cleanPeriodInSec, lifetimeGracePeriodInSec, cleanLimit, new SingleInstanceJedisLock());
|
110
|
|
- }
|
111
|
|
-
|
112
|
|
- /**
|
113
|
|
- * @since 1.1
|
114
|
|
- */
|
115
|
|
- public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec,
|
116
|
|
- long lifetimeGracePeriodInSec, int cleanLimit, JedisLock redisLock) {
|
117
|
109
|
this.connectionFactory = connectionFactory;
|
118
|
110
|
this.schedExecutor = schedExecutor;
|
119
|
111
|
this.cleanPeriod = cleanPeriodInSec;
|
120
|
112
|
this.cleanLimit = cleanLimit;
|
121
|
113
|
this.gracePeriod = lifetimeGracePeriodInSec;
|
122
|
|
- this.lock = redisLock;
|
|
114
|
+ this.redisLock = new RedisLockRegistry(connectionFactory, "Registration");
|
123
|
115
|
}
|
124
|
116
|
|
125
|
117
|
/* *************** Redis Key utility function **************** */
|
...
|
...
|
@@ -135,76 +127,79 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
135
|
127
|
return (prefix + registrationID).getBytes();
|
136
|
128
|
}
|
137
|
129
|
|
138
|
|
- private byte[] toLockKey(String endpoint) {
|
139
|
|
- return toKey(LOCK_EP, endpoint);
|
|
130
|
+ private String toLockKey(String endpoint) {
|
|
131
|
+ return new String(toKey(LOCK_EP, endpoint));
|
140
|
132
|
}
|
141
|
133
|
|
142
|
|
- private byte[] toLockKey(byte[] endpoint) {
|
143
|
|
- return toKey(LOCK_EP.getBytes(UTF_8), endpoint);
|
|
134
|
+ private String toLockKey(byte[] endpoint) {
|
|
135
|
+ return new String(toKey(LOCK_EP.getBytes(UTF_8), endpoint));
|
144
|
136
|
}
|
145
|
137
|
|
146
|
138
|
/* *************** Leshan Registration API **************** */
|
147
|
139
|
|
148
|
140
|
@Override
|
149
|
141
|
public Deregistration addRegistration(Registration registration) {
|
150
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
151
|
|
- byte[] lockValue = null;
|
152
|
|
- byte[] lockKey = toLockKey(registration.getEndpoint());
|
|
142
|
+ Lock lock = null;
|
|
143
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
144
|
+ String lockKey = toLockKey(registration.getEndpoint());
|
153
|
145
|
|
154
|
146
|
try {
|
155
|
|
- lockValue = lock.acquire(j, lockKey);
|
156
|
|
-
|
|
147
|
+ lock = redisLock.obtain(lockKey);
|
|
148
|
+ lock.lock();
|
157
|
149
|
// add registration
|
158
|
150
|
byte[] k = toEndpointKey(registration.getEndpoint());
|
159
|
|
- byte[] old = j.getSet(k, serializeReg(registration));
|
|
151
|
+ byte[] old = connection.getSet(k, serializeReg(registration));
|
160
|
152
|
|
161
|
153
|
// add registration: secondary indexes
|
162
|
154
|
byte[] regid_idx = toRegIdKey(registration.getId());
|
163
|
|
- j.set(regid_idx, registration.getEndpoint().getBytes(UTF_8));
|
|
155
|
+ connection.set(regid_idx, registration.getEndpoint().getBytes(UTF_8));
|
164
|
156
|
byte[] addr_idx = toRegAddrKey(registration.getSocketAddress());
|
165
|
|
- j.set(addr_idx, registration.getEndpoint().getBytes(UTF_8));
|
|
157
|
+ connection.set(addr_idx, registration.getEndpoint().getBytes(UTF_8));
|
166
|
158
|
|
167
|
159
|
// Add or update expiration
|
168
|
|
- addOrUpdateExpiration(j, registration);
|
|
160
|
+ addOrUpdateExpiration(connection, registration);
|
169
|
161
|
|
170
|
162
|
if (old != null) {
|
171
|
163
|
Registration oldRegistration = deserializeReg(old);
|
172
|
164
|
// remove old secondary index
|
173
|
165
|
if (!registration.getId().equals(oldRegistration.getId()))
|
174
|
|
- j.del(toRegIdKey(oldRegistration.getId()));
|
|
166
|
+ connection.del(toRegIdKey(oldRegistration.getId()));
|
175
|
167
|
if (!oldRegistration.getSocketAddress().equals(registration.getSocketAddress())) {
|
176
|
|
- removeAddrIndex(j, oldRegistration);
|
|
168
|
+ removeAddrIndex(connection, oldRegistration);
|
177
|
169
|
}
|
178
|
170
|
// remove old observation
|
179
|
|
- Collection<Observation> obsRemoved = unsafeRemoveAllObservations(j, oldRegistration.getId());
|
|
171
|
+ Collection<Observation> obsRemoved = unsafeRemoveAllObservations(connection, oldRegistration.getId());
|
180
|
172
|
|
181
|
173
|
return new Deregistration(oldRegistration, obsRemoved);
|
182
|
174
|
}
|
183
|
175
|
|
184
|
176
|
return null;
|
185
|
177
|
} finally {
|
186
|
|
- lock.release(j, lockKey, lockValue);
|
|
178
|
+ if (lock != null) {
|
|
179
|
+ lock.unlock();
|
|
180
|
+ }
|
187
|
181
|
}
|
188
|
182
|
}
|
189
|
183
|
}
|
190
|
184
|
|
191
|
185
|
@Override
|
192
|
186
|
public UpdatedRegistration updateRegistration(RegistrationUpdate update) {
|
193
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
|
187
|
+ Lock lock = null;
|
|
188
|
+ try (var connection = connectionFactory.getConnection()) {
|
194
|
189
|
|
195
|
190
|
// Fetch the registration ep by registration ID index
|
196
|
|
- byte[] ep = j.get(toRegIdKey(update.getRegistrationId()));
|
|
191
|
+ byte[] ep = connection.get(toRegIdKey(update.getRegistrationId()));
|
197
|
192
|
if (ep == null) {
|
198
|
193
|
return null;
|
199
|
194
|
}
|
200
|
195
|
|
201
|
|
- byte[] lockValue = null;
|
202
|
|
- byte[] lockKey = toLockKey(ep);
|
|
196
|
+ String lockKey = toLockKey(ep);
|
203
|
197
|
try {
|
204
|
|
- lockValue = lock.acquire(j, lockKey);
|
|
198
|
+ lock = redisLock.obtain(lockKey);
|
|
199
|
+ lock.lock();
|
205
|
200
|
|
206
|
201
|
// Fetch the registration
|
207
|
|
- byte[] data = j.get(toEndpointKey(ep));
|
|
202
|
+ byte[] data = connection.get(toEndpointKey(ep));
|
208
|
203
|
if (data == null) {
|
209
|
204
|
return null;
|
210
|
205
|
}
|
...
|
...
|
@@ -214,40 +209,42 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
214
|
209
|
Registration updatedRegistration = update.update(r);
|
215
|
210
|
|
216
|
211
|
// Store the new registration
|
217
|
|
- j.set(toEndpointKey(updatedRegistration.getEndpoint()), serializeReg(updatedRegistration));
|
|
212
|
+ connection.set(toEndpointKey(updatedRegistration.getEndpoint()), serializeReg(updatedRegistration));
|
218
|
213
|
|
219
|
214
|
// Add or update expiration
|
220
|
|
- addOrUpdateExpiration(j, updatedRegistration);
|
|
215
|
+ addOrUpdateExpiration(connection, updatedRegistration);
|
221
|
216
|
|
222
|
217
|
// Update secondary index :
|
223
|
218
|
// If registration is already associated to this address we don't care as we only want to keep the most
|
224
|
219
|
// recent binding.
|
225
|
220
|
byte[] addr_idx = toRegAddrKey(updatedRegistration.getSocketAddress());
|
226
|
|
- j.set(addr_idx, updatedRegistration.getEndpoint().getBytes(UTF_8));
|
|
221
|
+ connection.set(addr_idx, updatedRegistration.getEndpoint().getBytes(UTF_8));
|
227
|
222
|
if (!r.getSocketAddress().equals(updatedRegistration.getSocketAddress())) {
|
228
|
|
- removeAddrIndex(j, r);
|
|
223
|
+ removeAddrIndex(connection, r);
|
229
|
224
|
}
|
230
|
225
|
|
231
|
226
|
return new UpdatedRegistration(r, updatedRegistration);
|
232
|
227
|
|
233
|
228
|
} finally {
|
234
|
|
- lock.release(j, lockKey, lockValue);
|
|
229
|
+ if (lock != null) {
|
|
230
|
+ lock.unlock();
|
|
231
|
+ }
|
235
|
232
|
}
|
236
|
233
|
}
|
237
|
234
|
}
|
238
|
235
|
|
239
|
236
|
@Override
|
240
|
237
|
public Registration getRegistration(String registrationId) {
|
241
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
242
|
|
- return getRegistration(j, registrationId);
|
|
238
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
239
|
+ return getRegistration(connection, registrationId);
|
243
|
240
|
}
|
244
|
241
|
}
|
245
|
242
|
|
246
|
243
|
@Override
|
247
|
244
|
public Registration getRegistrationByEndpoint(String endpoint) {
|
248
|
245
|
Validate.notNull(endpoint);
|
249
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
250
|
|
- byte[] data = j.get(toEndpointKey(endpoint));
|
|
246
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
247
|
+ byte[] data = connection.get(toEndpointKey(endpoint));
|
251
|
248
|
if (data == null) {
|
252
|
249
|
return null;
|
253
|
250
|
}
|
...
|
...
|
@@ -258,12 +255,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
258
|
255
|
@Override
|
259
|
256
|
public Registration getRegistrationByAdress(InetSocketAddress address) {
|
260
|
257
|
Validate.notNull(address);
|
261
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
262
|
|
- byte[] ep = j.get(toRegAddrKey(address));
|
|
258
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
259
|
+ byte[] ep = connection.get(toRegAddrKey(address));
|
263
|
260
|
if (ep == null) {
|
264
|
261
|
return null;
|
265
|
262
|
}
|
266
|
|
- byte[] data = j.get(toEndpointKey(ep));
|
|
263
|
+ byte[] data = connection.get(toEndpointKey(ep));
|
267
|
264
|
if (data == null) {
|
268
|
265
|
return null;
|
269
|
266
|
}
|
...
|
...
|
@@ -273,140 +270,99 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
273
|
270
|
|
274
|
271
|
@Override
|
275
|
272
|
public Iterator<Registration> getAllRegistrations() {
|
276
|
|
- return new TbLwM2mRedisRegistrationStore.RedisIterator(connectionFactory, new ScanParams().match(REG_EP + "*").count(100));
|
277
|
|
- }
|
278
|
|
-
|
279
|
|
- protected class RedisIterator implements Iterator<Registration> {
|
280
|
|
-
|
281
|
|
- private final RedisConnectionFactory connectionFactory;
|
282
|
|
- private final ScanParams scanParams;
|
283
|
|
-
|
284
|
|
- private String cursor;
|
285
|
|
- private List<Registration> scanResult;
|
286
|
|
-
|
287
|
|
- public RedisIterator(RedisConnectionFactory connectionFactory, ScanParams scanParams) {
|
288
|
|
- this.connectionFactory = connectionFactory;
|
289
|
|
- this.scanParams = scanParams;
|
290
|
|
- // init scan result
|
291
|
|
- scanNext("0");
|
292
|
|
- }
|
293
|
|
-
|
294
|
|
- private void scanNext(String cursor) {
|
295
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
296
|
|
- do {
|
297
|
|
- ScanResult<byte[]> sr = j.scan(cursor.getBytes(), scanParams);
|
298
|
|
-
|
299
|
|
- this.scanResult = new ArrayList<>();
|
300
|
|
- if (sr.getResult() != null && !sr.getResult().isEmpty()) {
|
301
|
|
- for (byte[] value : j.mget(sr.getResult().toArray(new byte[][]{}))) {
|
302
|
|
- this.scanResult.add(deserializeReg(value));
|
303
|
|
- }
|
304
|
|
- }
|
305
|
|
-
|
306
|
|
- cursor = sr.getCursor();
|
307
|
|
- } while (!"0".equals(cursor) && scanResult.isEmpty());
|
308
|
|
-
|
309
|
|
- this.cursor = cursor;
|
310
|
|
- }
|
311
|
|
- }
|
312
|
|
-
|
313
|
|
- @Override
|
314
|
|
- public boolean hasNext() {
|
315
|
|
- if (!scanResult.isEmpty()) {
|
316
|
|
- return true;
|
317
|
|
- }
|
318
|
|
- if ("0".equals(cursor)) {
|
319
|
|
- // no more elements to scan
|
320
|
|
- return false;
|
321
|
|
- }
|
322
|
|
-
|
323
|
|
- // read more elements
|
324
|
|
- scanNext(cursor);
|
325
|
|
- return !scanResult.isEmpty();
|
326
|
|
- }
|
327
|
|
-
|
328
|
|
- @Override
|
329
|
|
- public Registration next() {
|
330
|
|
- if (!hasNext()) {
|
331
|
|
- throw new NoSuchElementException();
|
|
273
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
274
|
+ Collection<Registration> list = new LinkedList<>();
|
|
275
|
+ ScanOptions scanOptions = ScanOptions.scanOptions().count(100).match(REG_EP + "*").build();
|
|
276
|
+ List<Cursor<byte[]>> scans = new ArrayList<>();
|
|
277
|
+ if (connection instanceof RedisClusterConnection) {
|
|
278
|
+ ((RedisClusterConnection) connection).clusterGetNodes().forEach(node -> {
|
|
279
|
+ scans.add(((RedisClusterConnection) connection).scan(node, scanOptions));
|
|
280
|
+ });
|
|
281
|
+ } else {
|
|
282
|
+ scans.add(connection.scan(scanOptions));
|
332
|
283
|
}
|
333
|
|
- return scanResult.remove(0);
|
334
|
|
- }
|
335
|
284
|
|
336
|
|
- @Override
|
337
|
|
- public void remove() {
|
338
|
|
- throw new UnsupportedOperationException();
|
|
285
|
+ scans.forEach(scan -> {
|
|
286
|
+ scan.forEachRemaining(key -> {
|
|
287
|
+ byte[] element = connection.get(key);
|
|
288
|
+ list.add(deserializeReg(element));
|
|
289
|
+ });
|
|
290
|
+ });
|
|
291
|
+ return list.iterator();
|
339
|
292
|
}
|
340
|
293
|
}
|
341
|
294
|
|
342
|
295
|
@Override
|
343
|
296
|
public Deregistration removeRegistration(String registrationId) {
|
344
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
345
|
|
- return removeRegistration(j, registrationId, false);
|
|
297
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
298
|
+ return removeRegistration(connection, registrationId, false);
|
346
|
299
|
}
|
347
|
300
|
}
|
348
|
301
|
|
349
|
|
- private Deregistration removeRegistration(Jedis j, String registrationId, boolean removeOnlyIfNotAlive) {
|
|
302
|
+ private Deregistration removeRegistration(RedisConnection connection, String registrationId, boolean removeOnlyIfNotAlive) {
|
350
|
303
|
// fetch the client ep by registration ID index
|
351
|
|
- byte[] ep = j.get(toRegIdKey(registrationId));
|
|
304
|
+ byte[] ep = connection.get(toRegIdKey(registrationId));
|
352
|
305
|
if (ep == null) {
|
353
|
306
|
return null;
|
354
|
307
|
}
|
355
|
308
|
|
356
|
|
- byte[] lockValue = null;
|
357
|
|
- byte[] lockKey = toLockKey(ep);
|
|
309
|
+ Lock lock = null;
|
|
310
|
+ String lockKey = toLockKey(ep);
|
358
|
311
|
try {
|
359
|
|
- lockValue = lock.acquire(j, lockKey);
|
|
312
|
+ lock = redisLock.obtain(lockKey);
|
|
313
|
+ lock.lock();
|
360
|
314
|
|
361
|
315
|
// fetch the client
|
362
|
|
- byte[] data = j.get(toEndpointKey(ep));
|
|
316
|
+ byte[] data = connection.get(toEndpointKey(ep));
|
363
|
317
|
if (data == null) {
|
364
|
318
|
return null;
|
365
|
319
|
}
|
366
|
320
|
Registration r = deserializeReg(data);
|
367
|
321
|
|
368
|
322
|
if (!removeOnlyIfNotAlive || !r.isAlive(gracePeriod)) {
|
369
|
|
- long nbRemoved = j.del(toRegIdKey(r.getId()));
|
|
323
|
+ long nbRemoved = connection.del(toRegIdKey(r.getId()));
|
370
|
324
|
if (nbRemoved > 0) {
|
371
|
|
- j.del(toEndpointKey(r.getEndpoint()));
|
372
|
|
- Collection<Observation> obsRemoved = unsafeRemoveAllObservations(j, r.getId());
|
373
|
|
- removeAddrIndex(j, r);
|
374
|
|
- removeExpiration(j, r);
|
|
325
|
+ connection.del(toEndpointKey(r.getEndpoint()));
|
|
326
|
+ Collection<Observation> obsRemoved = unsafeRemoveAllObservations(connection, r.getId());
|
|
327
|
+ removeAddrIndex(connection, r);
|
|
328
|
+ removeExpiration(connection, r);
|
375
|
329
|
return new Deregistration(r, obsRemoved);
|
376
|
330
|
}
|
377
|
331
|
}
|
378
|
332
|
return null;
|
379
|
333
|
} finally {
|
380
|
|
- lock.release(j, lockKey, lockValue);
|
|
334
|
+ if (lock != null) {
|
|
335
|
+ lock.unlock();
|
|
336
|
+ }
|
381
|
337
|
}
|
382
|
338
|
}
|
383
|
339
|
|
384
|
|
- private void removeAddrIndex(Jedis j, Registration registration) {
|
|
340
|
+ private void removeAddrIndex(RedisConnection connection, Registration registration) {
|
385
|
341
|
// Watch the key to remove.
|
386
|
342
|
byte[] regAddrKey = toRegAddrKey(registration.getSocketAddress());
|
387
|
|
- j.watch(regAddrKey);
|
|
343
|
+ connection.watch(regAddrKey);
|
388
|
344
|
|
389
|
|
- byte[] epFromAddr = j.get(regAddrKey);
|
|
345
|
+ byte[] epFromAddr = connection.get(regAddrKey);
|
390
|
346
|
// Delete the key if needed.
|
391
|
347
|
if (Arrays.equals(epFromAddr, registration.getEndpoint().getBytes(UTF_8))) {
|
392
|
348
|
// Try to delete the key
|
393
|
|
- Transaction transaction = j.multi();
|
394
|
|
- transaction.del(regAddrKey);
|
395
|
|
- transaction.exec();
|
|
349
|
+ connection.multi();
|
|
350
|
+ connection.del(regAddrKey);
|
|
351
|
+ connection.exec();
|
396
|
352
|
// if transaction failed this is not an issue as the socket address is probably reused and we don't neeed to
|
397
|
353
|
// delete it anymore.
|
398
|
354
|
} else {
|
399
|
355
|
// the key must not be deleted.
|
400
|
|
- j.unwatch();
|
|
356
|
+ connection.unwatch();
|
401
|
357
|
}
|
402
|
358
|
}
|
403
|
359
|
|
404
|
|
- private void addOrUpdateExpiration(Jedis j, Registration registration) {
|
405
|
|
- j.zadd(EXP_EP, registration.getExpirationTimeStamp(gracePeriod), registration.getEndpoint().getBytes(UTF_8));
|
|
360
|
+ private void addOrUpdateExpiration(RedisConnection connection, Registration registration) {
|
|
361
|
+ connection.zAdd(EXP_EP, registration.getExpirationTimeStamp(gracePeriod), registration.getEndpoint().getBytes(UTF_8));
|
406
|
362
|
}
|
407
|
363
|
|
408
|
|
- private void removeExpiration(Jedis j, Registration registration) {
|
409
|
|
- j.zrem(EXP_EP, registration.getEndpoint().getBytes(UTF_8));
|
|
364
|
+ private void removeExpiration(RedisConnection connection, Registration registration) {
|
|
365
|
+ connection.zRem(EXP_EP, registration.getEndpoint().getBytes(UTF_8));
|
410
|
366
|
}
|
411
|
367
|
|
412
|
368
|
private byte[] toRegIdKey(String registrationId) {
|
...
|
...
|
@@ -441,33 +397,35 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
441
|
397
|
*/
|
442
|
398
|
@Override
|
443
|
399
|
public Collection<Observation> addObservation(String registrationId, Observation observation) {
|
444
|
|
-
|
445
|
400
|
List<Observation> removed = new ArrayList<>();
|
446
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
|
401
|
+ try (var connection = connectionFactory.getConnection()) {
|
447
|
402
|
|
448
|
403
|
// fetch the client ep by registration ID index
|
449
|
|
- byte[] ep = j.get(toRegIdKey(registrationId));
|
|
404
|
+ byte[] ep = connection.get(toRegIdKey(registrationId));
|
450
|
405
|
if (ep == null) {
|
451
|
406
|
return null;
|
452
|
407
|
}
|
453
|
408
|
|
454
|
|
- byte[] lockValue = null;
|
455
|
|
- byte[] lockKey = toLockKey(ep);
|
|
409
|
+ Lock lock = null;
|
|
410
|
+ String lockKey = toLockKey(ep);
|
456
|
411
|
|
457
|
412
|
try {
|
458
|
|
- lockValue = lock.acquire(j, lockKey);
|
|
413
|
+ lock = redisLock.obtain(lockKey);
|
|
414
|
+ lock.lock();
|
459
|
415
|
|
460
|
416
|
// cancel existing observations for the same path and registration id.
|
461
|
|
- for (Observation obs : getObservations(j, registrationId)) {
|
|
417
|
+ for (Observation obs : getObservations(connection, registrationId)) {
|
462
|
418
|
if (observation.getPath().equals(obs.getPath())
|
463
|
419
|
&& !Arrays.equals(observation.getId(), obs.getId())) {
|
464
|
420
|
removed.add(obs);
|
465
|
|
- unsafeRemoveObservation(j, registrationId, obs.getId());
|
|
421
|
+ unsafeRemoveObservation(connection, registrationId, obs.getId());
|
466
|
422
|
}
|
467
|
423
|
}
|
468
|
424
|
|
469
|
425
|
} finally {
|
470
|
|
- lock.release(j, lockKey, lockValue);
|
|
426
|
+ if (lock != null) {
|
|
427
|
+ lock.unlock();
|
|
428
|
+ }
|
471
|
429
|
}
|
472
|
430
|
}
|
473
|
431
|
return removed;
|
...
|
...
|
@@ -475,29 +433,32 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
475
|
433
|
|
476
|
434
|
@Override
|
477
|
435
|
public Observation removeObservation(String registrationId, byte[] observationId) {
|
478
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
|
436
|
+ try (var connection = connectionFactory.getConnection()) {
|
479
|
437
|
|
480
|
438
|
// fetch the client ep by registration ID index
|
481
|
|
- byte[] ep = j.get(toRegIdKey(registrationId));
|
|
439
|
+ byte[] ep = connection.get(toRegIdKey(registrationId));
|
482
|
440
|
if (ep == null) {
|
483
|
441
|
return null;
|
484
|
442
|
}
|
485
|
443
|
|
486
|
444
|
// remove observation
|
487
|
|
- byte[] lockValue = null;
|
488
|
|
- byte[] lockKey = toLockKey(ep);
|
|
445
|
+ Lock lock = null;
|
|
446
|
+ String lockKey = toLockKey(ep);
|
489
|
447
|
try {
|
490
|
|
- lockValue = lock.acquire(j, lockKey);
|
|
448
|
+ lock = redisLock.obtain(lockKey);
|
|
449
|
+ lock.lock();
|
491
|
450
|
|
492
|
451
|
Observation observation = build(get(new Token(observationId)));
|
493
|
452
|
if (observation != null && registrationId.equals(observation.getRegistrationId())) {
|
494
|
|
- unsafeRemoveObservation(j, registrationId, observationId);
|
|
453
|
+ unsafeRemoveObservation(connection, registrationId, observationId);
|
495
|
454
|
return observation;
|
496
|
455
|
}
|
497
|
456
|
return null;
|
498
|
457
|
|
499
|
458
|
} finally {
|
500
|
|
- lock.release(j, lockKey, lockValue);
|
|
459
|
+ if (lock != null) {
|
|
460
|
+ lock.unlock();
|
|
461
|
+ }
|
501
|
462
|
}
|
502
|
463
|
}
|
503
|
464
|
}
|
...
|
...
|
@@ -509,15 +470,15 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
509
|
470
|
|
510
|
471
|
@Override
|
511
|
472
|
public Collection<Observation> getObservations(String registrationId) {
|
512
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
513
|
|
- return getObservations(j, registrationId);
|
|
473
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
474
|
+ return getObservations(connection, registrationId);
|
514
|
475
|
}
|
515
|
476
|
}
|
516
|
477
|
|
517
|
|
- private Collection<Observation> getObservations(Jedis j, String registrationId) {
|
|
478
|
+ private Collection<Observation> getObservations(RedisConnection connection, String registrationId) {
|
518
|
479
|
Collection<Observation> result = new ArrayList<>();
|
519
|
|
- for (byte[] token : j.lrange(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, -1)) {
|
520
|
|
- byte[] obs = j.get(toKey(OBS_TKN, token));
|
|
480
|
+ for (byte[] token : connection.lRange(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, -1)) {
|
|
481
|
+ byte[] obs = connection.get(toKey(OBS_TKN, token));
|
521
|
482
|
if (obs != null) {
|
522
|
483
|
result.add(build(deserializeObs(obs)));
|
523
|
484
|
}
|
...
|
...
|
@@ -527,22 +488,24 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
527
|
488
|
|
528
|
489
|
@Override
|
529
|
490
|
public Collection<Observation> removeObservations(String registrationId) {
|
530
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
|
491
|
+ try (var connection = connectionFactory.getConnection()) {
|
531
|
492
|
// check registration exists
|
532
|
|
- Registration registration = getRegistration(j, registrationId);
|
|
493
|
+ Registration registration = getRegistration(connection, registrationId);
|
533
|
494
|
if (registration == null)
|
534
|
495
|
return Collections.emptyList();
|
535
|
496
|
|
536
|
497
|
// get endpoint and create lock
|
537
|
498
|
String endpoint = registration.getEndpoint();
|
538
|
|
- byte[] lockValue = null;
|
539
|
|
- byte[] lockKey = toKey(LOCK_EP, endpoint);
|
|
499
|
+ Lock lock = null;
|
|
500
|
+ String lockKey = toLockKey(endpoint);
|
540
|
501
|
try {
|
541
|
|
- lockValue = lock.acquire(j, lockKey);
|
542
|
|
-
|
543
|
|
- return unsafeRemoveAllObservations(j, registrationId);
|
|
502
|
+ lock = redisLock.obtain(lockKey);
|
|
503
|
+ lock.lock();
|
|
504
|
+ return unsafeRemoveAllObservations(connection, registrationId);
|
544
|
505
|
} finally {
|
545
|
|
- lock.release(j, lockKey, lockValue);
|
|
506
|
+ if (lock != null) {
|
|
507
|
+ lock.unlock();
|
|
508
|
+ }
|
546
|
509
|
}
|
547
|
510
|
}
|
548
|
511
|
}
|
...
|
...
|
@@ -565,31 +528,32 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
565
|
528
|
String endpoint = ObserveUtil.validateCoapObservation(obs);
|
566
|
529
|
org.eclipse.californium.core.observe.Observation previousObservation = null;
|
567
|
530
|
|
568
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
569
|
|
- byte[] lockValue = null;
|
570
|
|
- byte[] lockKey = toKey(LOCK_EP, endpoint);
|
|
531
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
532
|
+ Lock lock = null;
|
|
533
|
+ String lockKey = toLockKey(endpoint);
|
571
|
534
|
try {
|
572
|
|
- lockValue = lock.acquire(j, lockKey);
|
|
535
|
+ lock = redisLock.obtain(lockKey);
|
|
536
|
+ lock.lock();
|
573
|
537
|
|
574
|
538
|
String registrationId = ObserveUtil.extractRegistrationId(obs);
|
575
|
|
- if (!j.exists(toRegIdKey(registrationId)))
|
|
539
|
+ if (!connection.exists(toRegIdKey(registrationId)))
|
576
|
540
|
throw new ObservationStoreException("no registration for this Id");
|
577
|
541
|
byte[] key = toKey(OBS_TKN, obs.getRequest().getToken().getBytes());
|
578
|
542
|
byte[] serializeObs = serializeObs(obs);
|
579
|
543
|
byte[] previousValue;
|
580
|
544
|
if (ifAbsent) {
|
581
|
|
- previousValue = j.get(key);
|
|
545
|
+ previousValue = connection.get(key);
|
582
|
546
|
if (previousValue == null || previousValue.length == 0) {
|
583
|
|
- j.set(key, serializeObs);
|
|
547
|
+ connection.set(key, serializeObs);
|
584
|
548
|
} else {
|
585
|
549
|
return deserializeObs(previousValue);
|
586
|
550
|
}
|
587
|
551
|
} else {
|
588
|
|
- previousValue = j.getSet(key, serializeObs);
|
|
552
|
+ previousValue = connection.getSet(key, serializeObs);
|
589
|
553
|
}
|
590
|
554
|
|
591
|
555
|
// secondary index to get the list by registrationId
|
592
|
|
- j.lpush(toKey(OBS_TKNS_REGID_IDX, registrationId), obs.getRequest().getToken().getBytes());
|
|
556
|
+ connection.lPush(toKey(OBS_TKNS_REGID_IDX, registrationId), obs.getRequest().getToken().getBytes());
|
593
|
557
|
|
594
|
558
|
// log any collisions
|
595
|
559
|
if (previousValue != null && previousValue.length != 0) {
|
...
|
...
|
@@ -599,7 +563,9 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
599
|
563
|
previousObservation.getRequest(), obs.getRequest());
|
600
|
564
|
}
|
601
|
565
|
} finally {
|
602
|
|
- lock.release(j, lockKey, lockValue);
|
|
566
|
+ if (lock != null) {
|
|
567
|
+ lock.unlock();
|
|
568
|
+ }
|
603
|
569
|
}
|
604
|
570
|
}
|
605
|
571
|
return previousObservation;
|
...
|
...
|
@@ -607,17 +573,17 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
607
|
573
|
|
608
|
574
|
@Override
|
609
|
575
|
public void remove(Token token) {
|
610
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
|
576
|
+ try (var connection = connectionFactory.getConnection()) {
|
611
|
577
|
byte[] tokenKey = toKey(OBS_TKN, token.getBytes());
|
612
|
578
|
|
613
|
579
|
// fetch the observation by token
|
614
|
|
- byte[] serializedObs = j.get(tokenKey);
|
|
580
|
+ byte[] serializedObs = connection.get(tokenKey);
|
615
|
581
|
if (serializedObs == null)
|
616
|
582
|
return;
|
617
|
583
|
|
618
|
584
|
org.eclipse.californium.core.observe.Observation obs = deserializeObs(serializedObs);
|
619
|
585
|
String registrationId = ObserveUtil.extractRegistrationId(obs);
|
620
|
|
- Registration registration = getRegistration(j, registrationId);
|
|
586
|
+ Registration registration = getRegistration(connection, registrationId);
|
621
|
587
|
if (registration == null) {
|
622
|
588
|
LOG.warn("Unable to remove observation {}, registration {} does not exist anymore", obs.getRequest(),
|
623
|
589
|
registrationId);
|
...
|
...
|
@@ -625,14 +591,17 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
625
|
591
|
}
|
626
|
592
|
|
627
|
593
|
String endpoint = registration.getEndpoint();
|
628
|
|
- byte[] lockValue = null;
|
629
|
|
- byte[] lockKey = toKey(LOCK_EP, endpoint);
|
|
594
|
+ Lock lock = null;
|
|
595
|
+ String lockKey = toLockKey(endpoint);
|
630
|
596
|
try {
|
631
|
|
- lockValue = lock.acquire(j, lockKey);
|
|
597
|
+ lock = redisLock.obtain(lockKey);
|
|
598
|
+ lock.lock();
|
632
|
599
|
|
633
|
|
- unsafeRemoveObservation(j, registrationId, token.getBytes());
|
|
600
|
+ unsafeRemoveObservation(connection, registrationId, token.getBytes());
|
634
|
601
|
} finally {
|
635
|
|
- lock.release(j, lockKey, lockValue);
|
|
602
|
+ if (lock != null) {
|
|
603
|
+ lock.unlock();
|
|
604
|
+ }
|
636
|
605
|
}
|
637
|
606
|
}
|
638
|
607
|
|
...
|
...
|
@@ -640,8 +609,8 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
640
|
609
|
|
641
|
610
|
@Override
|
642
|
611
|
public org.eclipse.californium.core.observe.Observation get(Token token) {
|
643
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
644
|
|
- byte[] obs = j.get(toKey(OBS_TKN, token.getBytes()));
|
|
612
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
613
|
+ byte[] obs = connection.get(toKey(OBS_TKN, token.getBytes()));
|
645
|
614
|
if (obs == null) {
|
646
|
615
|
return null;
|
647
|
616
|
} else {
|
...
|
...
|
@@ -652,12 +621,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
652
|
621
|
|
653
|
622
|
/* *************** Observation utility functions **************** */
|
654
|
623
|
|
655
|
|
- private Registration getRegistration(Jedis j, String registrationId) {
|
656
|
|
- byte[] ep = j.get(toRegIdKey(registrationId));
|
|
624
|
+ private Registration getRegistration(RedisConnection connection, String registrationId) {
|
|
625
|
+ byte[] ep = connection.get(toRegIdKey(registrationId));
|
657
|
626
|
if (ep == null) {
|
658
|
627
|
return null;
|
659
|
628
|
}
|
660
|
|
- byte[] data = j.get(toEndpointKey(ep));
|
|
629
|
+ byte[] data = connection.get(toEndpointKey(ep));
|
661
|
630
|
if (data == null) {
|
662
|
631
|
return null;
|
663
|
632
|
}
|
...
|
...
|
@@ -665,25 +634,25 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
665
|
634
|
return deserializeReg(data);
|
666
|
635
|
}
|
667
|
636
|
|
668
|
|
- private void unsafeRemoveObservation(Jedis j, String registrationId, byte[] observationId) {
|
669
|
|
- if (j.del(toKey(OBS_TKN, observationId)) > 0L) {
|
670
|
|
- j.lrem(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, observationId);
|
|
637
|
+ private void unsafeRemoveObservation(RedisConnection connection, String registrationId, byte[] observationId) {
|
|
638
|
+ if (connection.del(toKey(OBS_TKN, observationId)) > 0L) {
|
|
639
|
+ connection.lRem(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, observationId);
|
671
|
640
|
}
|
672
|
641
|
}
|
673
|
642
|
|
674
|
|
- private Collection<Observation> unsafeRemoveAllObservations(Jedis j, String registrationId) {
|
|
643
|
+ private Collection<Observation> unsafeRemoveAllObservations(RedisConnection connection, String registrationId) {
|
675
|
644
|
Collection<Observation> removed = new ArrayList<>();
|
676
|
645
|
byte[] regIdKey = toKey(OBS_TKNS_REGID_IDX, registrationId);
|
677
|
646
|
|
678
|
647
|
// fetch all observations by token
|
679
|
|
- for (byte[] token : j.lrange(regIdKey, 0, -1)) {
|
680
|
|
- byte[] obs = j.get(toKey(OBS_TKN, token));
|
|
648
|
+ for (byte[] token : connection.lRange(regIdKey, 0, -1)) {
|
|
649
|
+ byte[] obs = connection.get(toKey(OBS_TKN, token));
|
681
|
650
|
if (obs != null) {
|
682
|
651
|
removed.add(build(deserializeObs(obs)));
|
683
|
652
|
}
|
684
|
|
- j.del(toKey(OBS_TKN, token));
|
|
653
|
+ connection.del(toKey(OBS_TKN, token));
|
685
|
654
|
}
|
686
|
|
- j.del(regIdKey);
|
|
655
|
+ connection.del(regIdKey);
|
687
|
656
|
|
688
|
657
|
return removed;
|
689
|
658
|
}
|
...
|
...
|
@@ -754,14 +723,14 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto |
754
|
723
|
@Override
|
755
|
724
|
public void run() {
|
756
|
725
|
|
757
|
|
- try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
|
758
|
|
- Set<byte[]> endpointsExpired = j.zrangeByScore(EXP_EP, Double.NEGATIVE_INFINITY,
|
|
726
|
+ try (var connection = connectionFactory.getConnection()) {
|
|
727
|
+ Set<byte[]> endpointsExpired = connection.zRangeByScore(EXP_EP, Double.NEGATIVE_INFINITY,
|
759
|
728
|
System.currentTimeMillis(), 0, cleanLimit);
|
760
|
729
|
|
761
|
730
|
for (byte[] endpoint : endpointsExpired) {
|
762
|
|
- Registration r = deserializeReg(j.get(toEndpointKey(endpoint)));
|
|
731
|
+ Registration r = deserializeReg(connection.get(toEndpointKey(endpoint)));
|
763
|
732
|
if (!r.isAlive(gracePeriod)) {
|
764
|
|
- Deregistration dereg = removeRegistration(j, r.getId(), true);
|
|
733
|
+ Deregistration dereg = removeRegistration(connection, r.getId(), true);
|
765
|
734
|
if (dereg != null)
|
766
|
735
|
expirationListener.registrationExpired(dereg.getRegistration(), dereg.getObservations());
|
767
|
736
|
}
|
...
|
...
|
|