1 package com.atlassian.vcache.internal.legacy;
2
3 import com.atlassian.cache.Cache;
4 import com.atlassian.vcache.JvmCache;
5 import com.atlassian.vcache.internal.core.RecursionDetector;
6 import com.atlassian.vcache.internal.core.service.LocalCacheUtils;
7
8 import java.util.Arrays;
9 import java.util.HashSet;
10 import java.util.Map;
11 import java.util.Optional;
12 import java.util.Set;
13 import java.util.concurrent.locks.ReentrantLock;
14 import java.util.function.Function;
15 import java.util.function.Supplier;
16
17 import static java.util.Objects.requireNonNull;
18
19
20
21
22
23
24
25
26 class LegacyJvmCache<K, V> implements JvmCache<K, V> {
27 private final ReentrantLock globalLock = new ReentrantLock();
28 private final Cache<K, V> delegate;
29 private final RecursionDetector<K> recursionDetector = new RecursionDetector<>();
30
31 LegacyJvmCache(Cache<K, V> delegate) {
32 this.delegate = requireNonNull(delegate);
33 }
34
35 @Override
36 public Set<K> getKeys() {
37 return withLock(() -> new HashSet<>(delegate.getKeys()));
38 }
39
40 @Override
41 public Optional<V> get(K key) {
42 return withLock(() -> Optional.ofNullable(delegate.get(key)));
43 }
44
45 @Override
46 public V get(K key, Supplier<? extends V> supplier) {
47 try (RecursionDetector.Guard<K> ignored = recursionDetector.guardOn(key)) {
48 return withLock(() -> delegate.get(key, supplier::get));
49 }
50 }
51
52 @SafeVarargs
53 @Override
54 public final Map<K, V> getBulk(Function<Set<K>, Map<K, V>> factory, K... keys) {
55
56 return getBulk(factory, Arrays.asList(keys));
57 }
58
59 @Override
60 public Map<K, V> getBulk(Function<Set<K>, Map<K, V>> factory, Iterable<K> keys) {
61 return withLock(() -> LocalCacheUtils.getBulk(
62 factory,
63 keys,
64 this::get,
65 args -> put(args.key, args.value),
66 recursionDetector));
67 }
68
69 @Override
70 public void put(K key, V value) {
71 withLock(() -> delegate.put(key, value));
72 }
73
74 @Override
75 public Optional<V> putIfAbsent(K key, V value) {
76 return withLock(() -> Optional.ofNullable(delegate.putIfAbsent(key, value)));
77 }
78
79 @Override
80 public boolean replaceIf(K key, V currentValue, V newValue) {
81 return withLock(() -> delegate.replace(key, currentValue, newValue));
82 }
83
84 @Override
85 public boolean removeIf(K key, V value) {
86 return withLock(() -> delegate.remove(key, value));
87 }
88
89 @Override
90 public void remove(K key) {
91 withLock(() -> delegate.remove(key));
92 }
93
94 @Override
95 public void removeAll() {
96 withLock(delegate::removeAll);
97 }
98
99 @Override
100 public String getName() {
101 return delegate.getName();
102 }
103
104 private <R> R withLock(Supplier<R> supplier) {
105 globalLock.lock();
106 try {
107 return supplier.get();
108 } finally {
109 globalLock.unlock();
110 }
111 }
112
113 private void withLock(Runnable runner) {
114 globalLock.lock();
115 try {
116 runner.run();
117 } finally {
118 globalLock.unlock();
119 }
120 }
121 }