Skip to content

Commit f3722cf

Browse files
authored
synchronize when placing a new entry to the cache (#91)
1 parent c6f192e commit f3722cf

File tree

1 file changed

+43
-32
lines changed

1 file changed

+43
-32
lines changed

src/main/java/com/aerospike/mapper/tools/ClassCache.java

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
package com.aerospike.mapper.tools;
22

3-
import java.util.HashMap;
4-
import java.util.Map;
5-
6-
import javax.validation.constraints.NotNull;
7-
83
import com.aerospike.client.AerospikeException;
94
import com.aerospike.client.IAerospikeClient;
105
import com.aerospike.client.policy.BatchPolicy;
@@ -18,6 +13,10 @@
1813
import com.aerospike.mapper.tools.configuration.Configuration;
1914
import com.aerospike.mapper.tools.utils.TypeUtils;
2015

16+
import javax.validation.constraints.NotNull;
17+
import java.util.HashMap;
18+
import java.util.Map;
19+
2120
public class ClassCache {
2221
private static final ClassCache instance = new ClassCache();
2322

@@ -33,49 +32,61 @@ enum PolicyType {
3332
QUERY
3433
}
3534

36-
private final Map<Class<?>, ClassCacheEntry> cacheMap = new HashMap<>();
35+
private final Map<Class<?>, ClassCacheEntry<?>> cacheMap = new HashMap<>();
3736
private final Map<String, ClassConfig> classesConfig = new HashMap<>();
3837
private final Map<PolicyType, Policy> defaultPolicies = new HashMap<>();
39-
private final Map<String, ClassCacheEntry> storedNameToCacheEntry = new HashMap<>();
38+
private final Map<String, ClassCacheEntry<?>> storedNameToCacheEntry = new HashMap<>();
4039
private final Map<PolicyType, Map<Class<?>, Policy>> childrenPolicies = new HashMap<>();
4140
private final Map<PolicyType, Map<Class<?>, Policy>> specificPolicies = new HashMap<>();
4241

42+
private final Object lock = new Object();
43+
4344
private ClassCache() {
4445
for (PolicyType thisType : PolicyType.values()) {
4546
this.childrenPolicies.put(thisType, new HashMap<>());
4647
this.specificPolicies.put(thisType, new HashMap<>());
4748
}
4849
}
4950

51+
@SuppressWarnings("unchecked")
5052
public <T> ClassCacheEntry<T> loadClass(@NotNull Class<T> clazz, IBaseAeroMapper mapper) {
51-
if (clazz.isPrimitive() || clazz.equals(Object.class) || clazz.equals(String.class) || clazz.equals(Character.class) || Number.class.isAssignableFrom(clazz)) {
53+
if (clazz.isPrimitive() || clazz.equals(Object.class) || clazz.equals(String.class)
54+
|| clazz.equals(Character.class) || Number.class.isAssignableFrom(clazz)) {
5255
return null;
5356
}
54-
ClassCacheEntry<T> entry = cacheMap.get(clazz);
57+
58+
ClassCacheEntry<T> entry = (ClassCacheEntry<T>) cacheMap.get(clazz);
5559
if (entry == null) {
56-
try {
57-
// Construct a class cache entry. This must be done in 2 steps, one creating the entry and the other finalizing construction of
58-
// it. This is to cater for classes which recursively refer to themselves, such as
59-
// public static class A {
60-
// @AerospikeKey
61-
// public int id;
62-
// public A a;
63-
// }
64-
entry = new ClassCacheEntry<>(clazz, mapper, getClassConfig(clazz),
65-
determinePolicy(clazz, PolicyType.READ),
66-
(WritePolicy) determinePolicy(clazz, PolicyType.WRITE),
67-
(BatchPolicy) determinePolicy(clazz, PolicyType.BATCH),
68-
(QueryPolicy) determinePolicy(clazz, PolicyType.QUERY),
69-
(ScanPolicy) determinePolicy(clazz, PolicyType.SCAN));
70-
} catch (NotAnnotatedClass nae) {
71-
return null;
72-
}
73-
cacheMap.put(clazz, entry);
74-
try {
75-
entry.construct();
76-
} catch (IllegalArgumentException iae) {
77-
cacheMap.remove(clazz);
78-
return null;
60+
synchronized (lock) {
61+
entry = (ClassCacheEntry<T>) cacheMap.get(clazz);
62+
if (entry == null) {
63+
try {
64+
// Construct a class cache entry. This must be done in 2 steps, one creating the entry
65+
// and the other finalizing construction of it.
66+
// This is to cater for classes which recursively refer to themselves, such as
67+
// public static class A {
68+
// @AerospikeKey
69+
// public int id;
70+
// public A a;
71+
// }
72+
entry = new ClassCacheEntry<>(clazz, mapper, getClassConfig(clazz),
73+
determinePolicy(clazz, PolicyType.READ),
74+
(WritePolicy) determinePolicy(clazz, PolicyType.WRITE),
75+
(BatchPolicy) determinePolicy(clazz, PolicyType.BATCH),
76+
(QueryPolicy) determinePolicy(clazz, PolicyType.QUERY),
77+
(ScanPolicy) determinePolicy(clazz, PolicyType.SCAN));
78+
79+
} catch (NotAnnotatedClass nae) {
80+
return null;
81+
}
82+
cacheMap.put(clazz, entry);
83+
try {
84+
entry.construct();
85+
} catch (IllegalArgumentException iae) {
86+
cacheMap.remove(clazz);
87+
return null;
88+
}
89+
}
7990
}
8091
}
8192
return entry;

0 commit comments

Comments
 (0)