summaryrefslogtreecommitdiffstats
path: root/gerrit-server/src/main/java/com/google/gerrit/server/cache/CacheProvider.java
blob: 0ba424f2cd0d953e6cfa89d270cbe9baf74a9e11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.cache;

import static com.google.gerrit.server.cache.EvictionPolicy.LFU;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.SECONDS;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;

import net.sf.ehcache.Ehcache;

import java.util.concurrent.TimeUnit;

final class CacheProvider<K, V> implements Provider<Cache<K, V>>,
    NamedCacheBinding<K, V>, UnnamedCacheBinding<K, V> {
  private final CacheModule module;
  private final boolean disk;
  private int memoryLimit;
  private int diskLimit;
  private long maxAge;
  private EvictionPolicy evictionPolicy;
  private String cacheName;
  private ProxyEhcache cache;
  private Provider<EntryCreator<K, V>> entryCreator;

  CacheProvider(final boolean disk, CacheModule module) {
    this.disk = disk;
    this.module = module;

    memoryLimit(1024);
    maxAge(90, DAYS);
    evictionPolicy(LFU);

    if (disk) {
      diskLimit(16384);
    }
  }

  @Inject
  void setCachePool(final CachePool pool) {
    this.cache = pool.register(this);
  }

  void bind(final Ehcache ehcache) {
    cache.bind(ehcache);
  }

  String getName() {
    if (cacheName == null) {
      throw new ProvisionException("Cache has no name");
    }
    return cacheName;
  }

  boolean disk() {
    return disk;
  }

  int memoryLimit() {
    return memoryLimit;
  }

  int diskLimit() {
    return diskLimit;
  }

  long maxAge() {
    return maxAge;
  }

  EvictionPolicy evictionPolicy() {
    return evictionPolicy;
  }

  public NamedCacheBinding<K, V> name(final String name) {
    if (cacheName != null) {
      throw new IllegalStateException("Cache name already set");
    }
    cacheName = name;
    return this;
  }

  public NamedCacheBinding<K, V> memoryLimit(final int objects) {
    memoryLimit = objects;
    return this;
  }

  public NamedCacheBinding<K, V> diskLimit(final int objects) {
    if (!disk) {
      // TODO This should really be a compile time type error, but I'm
      // too lazy to create the mess of permutations required to setup
      // type safe returns for bindings in our little DSL.
      //
      throw new IllegalStateException("Cache is not disk based");
    }
    diskLimit = objects;
    return this;
  }

  public NamedCacheBinding<K, V> maxAge(final long duration, final TimeUnit unit) {
    maxAge = SECONDS.convert(duration, unit);
    return this;
  }

  @Override
  public NamedCacheBinding<K, V> evictionPolicy(final EvictionPolicy policy) {
    evictionPolicy = policy;
    return this;
  }

  public NamedCacheBinding<K, V> populateWith(
      Class<? extends EntryCreator<K, V>> creator) {
    entryCreator = module.getEntryCreator(this, creator);
    return this;
  }

  public Cache<K, V> get() {
    if (cache == null) {
      throw new ProvisionException("Cache \"" + cacheName + "\" not available");
    }
    if (entryCreator != null) {
      return new PopulatingCache<K, V>(cache, entryCreator.get());
    }
    return new SimpleCache<K, V>(cache);
  }
}