1 package com.atlassian.cache.hazelcast;
2
3 import java.util.Random;
4
5 import com.atlassian.cache.CacheSettings;
6
7 import com.hazelcast.config.EvictionPolicy;
8 import com.hazelcast.config.MapConfig;
9 import com.hazelcast.config.MaxSizeConfig;
10 import com.hazelcast.config.NearCacheConfig;
11
12 import static com.hazelcast.config.MaxSizeConfig.MaxSizePolicy.PER_NODE;
13
14
15
16
17
18
19 public class HazelcastMapConfigConfigurator
20 {
21
22
23
24 public static final int HYBRID_MULTIPLIER = 2;
25
26 public static final int NEAR_CACHE_EXPIRY_RATIO = Integer.getInteger("atlassian.cache.nearCacheExpiryRatio", 75);
27
28 public MapConfig configureMapConfig(CacheSettings settings, MapConfig mapConfig)
29 {
30 boolean hybrid = !settings.getReplicateViaCopy(true);
31 Integer multiplier = hybrid ? HYBRID_MULTIPLIER : 1;
32 Integer maxEntries = settings.getMaxEntries();
33
34 final NearCacheConfig nearCacheConfig = mapConfig.getNearCacheConfig() == null ?
35 new NearCacheConfig() :
36 new NearCacheConfig(mapConfig.getNearCacheConfig());
37
38 if (maxEntries != null)
39 {
40 final int maxSize = multiplier * maxEntries;
41
42 mapConfig.setMaxSizeConfig(new MaxSizeConfig().setMaxSizePolicy(PER_NODE).setSize(maxSize));
43 mapConfig.setEvictionPolicy(EvictionPolicy.LFU);
44
45 nearCacheConfig.setMaxSize(maxSize);
46 nearCacheConfig.setEvictionPolicy(EvictionPolicy.LFU.name());
47 }
48
49 final Long expireAfterAccess = settings.getExpireAfterAccess();
50 if (expireAfterAccess != null)
51 {
52 final int maxIdleSeconds = multiplier * roundUpToWholeSeconds(expireAfterAccess);
53
54 mapConfig.setMaxIdleSeconds(maxIdleSeconds);
55
56
57
58
59
60
61
62
63
64
65 int jitter = new Random().nextInt(30) - 15;
66 int nearCacheTtl = (int) Math.round(((NEAR_CACHE_EXPIRY_RATIO + jitter) * maxIdleSeconds) / 100.0);
67 nearCacheConfig.setTimeToLiveSeconds(Math.max(1, nearCacheTtl));
68 }
69
70 final Long expireAfterWrite = settings.getExpireAfterWrite();
71 if (expireAfterWrite != null)
72 {
73 final int timeToLiveSeconds = multiplier * roundUpToWholeSeconds(expireAfterWrite);
74
75 mapConfig.setTimeToLiveSeconds(timeToLiveSeconds);
76
77 nearCacheConfig.setTimeToLiveSeconds(timeToLiveSeconds);
78 }
79
80 final boolean nearCache = settings.getReplicateAsynchronously(true);
81 if (nearCache)
82 {
83 mapConfig.setNearCacheConfig(nearCacheConfig);
84 }
85 else
86 {
87 mapConfig.setNearCacheConfig(null);
88 }
89
90 return mapConfig;
91 }
92
93 private static int roundUpToWholeSeconds(final Long expireAfterAccess)
94 {
95 return (int) Math.ceil(expireAfterAccess / 1000d);
96 }
97 }