Line data Source code
1 : // Copyright (C) 2009 The Android Open Source Project
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : package com.google.gerrit.server.cache;
16 :
17 : import com.google.common.cache.Cache;
18 : import com.google.common.cache.CacheLoader;
19 : import com.google.common.cache.LoadingCache;
20 : import com.google.common.cache.Weigher;
21 : import com.google.gerrit.extensions.annotations.Exports;
22 : import com.google.gerrit.extensions.config.FactoryModule;
23 : import com.google.gerrit.server.cache.serialize.JavaCacheSerializer;
24 : import com.google.inject.Key;
25 : import com.google.inject.Provider;
26 : import com.google.inject.Scopes;
27 : import com.google.inject.TypeLiteral;
28 : import com.google.inject.name.Named;
29 : import com.google.inject.name.Names;
30 : import com.google.inject.util.Types;
31 : import java.lang.reflect.Type;
32 :
33 : /** Miniature DSL to support binding {@link Cache} instances in Guice. */
34 152 : public abstract class CacheModule extends FactoryModule {
35 : public static final String MEMORY_MODULE = "cache-memory";
36 : public static final String PERSISTENT_MODULE = "cache-persistent";
37 :
38 152 : private static final TypeLiteral<Cache<?, ?>> ANY_CACHE = new TypeLiteral<>() {};
39 :
40 : /**
41 : * Declare a named in-memory cache.
42 : *
43 : * @param <K> type of key used to lookup entries.
44 : * @param <V> type of value stored by the cache.
45 : * @return binding to describe the cache.
46 : */
47 : protected <K, V> CacheBinding<K, V> cache(String name, Class<K> keyType, Class<V> valType) {
48 152 : return cache(name, TypeLiteral.get(keyType), TypeLiteral.get(valType));
49 : }
50 :
51 : /**
52 : * Declare a named in-memory cache.
53 : *
54 : * @param <K> type of key used to lookup entries.
55 : * @param <V> type of value stored by the cache.
56 : * @return binding to describe the cache.
57 : */
58 : protected <K, V> CacheBinding<K, V> cache(String name, Class<K> keyType, TypeLiteral<V> valType) {
59 152 : return cache(name, TypeLiteral.get(keyType), valType);
60 : }
61 :
62 : /**
63 : * Declare a named in-memory cache.
64 : *
65 : * @param <K> type of key used to lookup entries.
66 : * @param <V> type of value stored by the cache.
67 : * @return binding to describe the cache.
68 : */
69 : protected <K, V> CacheBinding<K, V> cache(
70 : String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) {
71 152 : CacheProvider<K, V> m = new CacheProvider<>(this, name, keyType, valType);
72 152 : bindCache(m, name, keyType, valType);
73 152 : return m;
74 : }
75 :
76 : <K, V> Provider<CacheLoader<K, V>> bindCacheLoader(
77 : CacheProvider<K, V> m, Class<? extends CacheLoader<K, V>> impl) {
78 152 : Type type =
79 152 : Types.newParameterizedType(Cache.class, m.keyType().getType(), m.valueType().getType());
80 :
81 152 : Type loadingType =
82 152 : Types.newParameterizedType(
83 152 : LoadingCache.class, m.keyType().getType(), m.valueType().getType());
84 :
85 152 : Type loaderType =
86 152 : Types.newParameterizedType(
87 152 : CacheLoader.class, m.keyType().getType(), m.valueType().getType());
88 :
89 : @SuppressWarnings("unchecked")
90 152 : Key<LoadingCache<K, V>> key = (Key<LoadingCache<K, V>>) Key.get(type, Names.named(m.name));
91 :
92 : @SuppressWarnings("unchecked")
93 152 : Key<LoadingCache<K, V>> loadingKey =
94 152 : (Key<LoadingCache<K, V>>) Key.get(loadingType, Names.named(m.name));
95 :
96 : @SuppressWarnings("unchecked")
97 152 : Key<CacheLoader<K, V>> loaderKey =
98 152 : (Key<CacheLoader<K, V>>) Key.get(loaderType, Names.named(m.name));
99 :
100 152 : bind(loaderKey).to(impl).in(Scopes.SINGLETON);
101 152 : bind(loadingKey).to(key);
102 152 : return getProvider(loaderKey);
103 : }
104 :
105 : <K, V> Provider<Weigher<K, V>> bindWeigher(
106 : CacheProvider<K, V> m, Class<? extends Weigher<K, V>> impl) {
107 152 : Type weigherType =
108 152 : Types.newParameterizedType(Weigher.class, m.keyType().getType(), m.valueType().getType());
109 :
110 : @SuppressWarnings("unchecked")
111 152 : Key<Weigher<K, V>> key = (Key<Weigher<K, V>>) Key.get(weigherType, Names.named(m.name));
112 :
113 152 : bind(key).to(impl).in(Scopes.SINGLETON);
114 152 : return getProvider(key);
115 : }
116 :
117 : /**
118 : * Declare a named in-memory/on-disk cache.
119 : *
120 : * @param <K> type of key used to lookup entries.
121 : * @param <V> type of value stored by the cache.
122 : * @return binding to describe the cache.
123 : */
124 : protected <K, V> PersistentCacheBinding<K, V> persist(
125 : String name, Class<K> keyType, Class<V> valType) {
126 152 : return persist(name, TypeLiteral.get(keyType), TypeLiteral.get(valType));
127 : }
128 :
129 : /**
130 : * Declare a named in-memory/on-disk cache.
131 : *
132 : * @param <K> type of key used to lookup entries.
133 : * @param <V> type of value stored by the cache.
134 : * @return binding to describe the cache.
135 : */
136 : protected <K, V> PersistentCacheBinding<K, V> persist(
137 : String name, Class<K> keyType, TypeLiteral<V> valType) {
138 152 : return persist(name, TypeLiteral.get(keyType), valType);
139 : }
140 :
141 : /**
142 : * Declare a named in-memory/on-disk cache.
143 : *
144 : * @param <K> type of key used to lookup entries.
145 : * @param <V> type of value stored by the cache.
146 : * @return binding to describe the cache.
147 : */
148 : protected <K, V> PersistentCacheBinding<K, V> persist(
149 : String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) {
150 152 : PersistentCacheProvider<K, V> m = new PersistentCacheProvider<>(this, name, keyType, valType);
151 152 : bindCache(m, name, keyType, valType);
152 :
153 152 : Type cacheDefType =
154 152 : Types.newParameterizedType(PersistentCacheDef.class, keyType.getType(), valType.getType());
155 : @SuppressWarnings("unchecked")
156 152 : Key<PersistentCacheDef<K, V>> cacheDefKey =
157 152 : (Key<PersistentCacheDef<K, V>>) Key.get(cacheDefType, Names.named(name));
158 152 : bind(cacheDefKey).toInstance(m);
159 :
160 : // TODO(dborowitz): Once default Java serialization is removed, leave no default.
161 152 : return m.version(0)
162 152 : .keySerializer(new JavaCacheSerializer<>())
163 152 : .valueSerializer(new JavaCacheSerializer<>());
164 : }
165 :
166 : private <K, V> void bindCache(
167 : CacheProvider<K, V> m, String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) {
168 152 : Type type = Types.newParameterizedType(Cache.class, keyType.getType(), valType.getType());
169 152 : Named named = Names.named(name);
170 :
171 : @SuppressWarnings("unchecked")
172 152 : Key<Cache<K, V>> key = (Key<Cache<K, V>>) Key.get(type, named);
173 152 : bind(key).toProvider(m).asEagerSingleton();
174 152 : bind(ANY_CACHE).annotatedWith(Exports.named(name)).to(key);
175 :
176 152 : Type cacheDefType =
177 152 : Types.newParameterizedType(CacheDef.class, keyType.getType(), valType.getType());
178 : @SuppressWarnings("unchecked")
179 152 : Key<CacheDef<K, V>> cacheDefKey = (Key<CacheDef<K, V>>) Key.get(cacheDefType, named);
180 152 : bind(cacheDefKey).toInstance(m);
181 :
182 152 : m.maximumWeight(1024);
183 152 : }
184 : }
|