2
* Copyright 2003-2010 Terracotta, Inc.
2
* Copyright Terracotta, Inc.
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
package net.sf.ehcache.terracotta;
19
import java.io.IOException;
19
22
import net.sf.ehcache.CacheException;
23
import net.sf.ehcache.CacheManager;
24
import net.sf.ehcache.DiskStorePathManager;
20
25
import net.sf.ehcache.Disposable;
21
26
import net.sf.ehcache.Ehcache;
22
27
import net.sf.ehcache.Status;
23
28
import net.sf.ehcache.distribution.RemoteCacheException;
24
29
import net.sf.ehcache.store.MemoryLimitedCacheLoader;
25
31
import org.slf4j.Logger;
26
32
import org.slf4j.LoggerFactory;
28
import java.io.IOException;
32
35
* A {@link net.sf.ehcache.bootstrap.BootstrapCacheLoader} that will load Elements into a Terracotta clustered cache, based on a previously
33
36
* snapshotted key set. It is also responsible to create snapshot files to disk
34
38
* @author Alex Snaps
36
40
public class TerracottaBootstrapCacheLoader extends MemoryLimitedCacheLoader implements Disposable {
51
55
private final boolean doKeySnapshot;
52
56
private final boolean doKeySnapshotOnDedicatedThread;
53
57
private final long interval;
54
private final String directory;
58
private final DiskStorePathManager diskStorePathManager;
56
60
private volatile KeySnapshotter keySnapshotter;
57
61
private volatile boolean immediateShutdown;
58
62
private volatile boolean doKeySnapshotOnDispose;
60
private TerracottaBootstrapCacheLoader(final boolean doKeySnapshot, final boolean aSynchronous,
61
final String directory, final long interval, final boolean doKeySnapshotOnDedicatedThread) {
64
private TerracottaBootstrapCacheLoader(final boolean doKeySnapshot, final boolean aSynchronous, final String directory,
65
final long interval, final boolean doKeySnapshotOnDedicatedThread) {
62
66
this.aSynchronous = aSynchronous;
63
67
this.doKeySnapshot = doKeySnapshot;
64
68
this.doKeySnapshotOnDedicatedThread = doKeySnapshotOnDedicatedThread;
65
69
this.interval = interval;
66
this.directory = directory;
70
this.diskStorePathManager = directory != null ? new DiskStorePathManager(directory) : null;
71
76
* @param asynchronous do the loading asynchronously, or synchronously
72
77
* @param directory the directory to read snapshot files from, and write them to
73
78
* @param doKeySnapshots Whether to do keysnapshotting
81
87
* @param asynchronous do the loading asynchronously, or synchronously
82
88
* @param directory the directory to read snapshot files from, and write them to
83
89
* @param interval the interval in seconds at which the snapshots of the local key set has to occur
91
98
* @param asynchronous do the loading asynchronously, or synchronously
92
99
* @param directory the directory to read snapshot files from, and write them to
93
100
* @param interval the interval in seconds at which the snapshots of the local key set has to occur
94
101
* @param onDedicatedThread whether to do the snapshot on a dedicated thread or using the CacheManager's
95
* {@link java.util.concurrent.ScheduledExecutorService ScheduledExecutorService}
102
* {@link java.util.concurrent.ScheduledExecutorService ScheduledExecutorService}
97
104
public TerracottaBootstrapCacheLoader(final boolean asynchronous, String directory, long interval, boolean onDedicatedThread) {
98
105
this(true, asynchronous, directory, interval, onDedicatedThread);
111
119
* Sets whether the disposal of the instance will let the potential current key set being written to disk finish, or whether the
112
120
* shutdown will be immediate
113
122
* @param immediateShutdown true if immediate, false to let the snapshot finish
115
124
public void setImmediateShutdown(final boolean immediateShutdown) {
122
131
public void load(final Ehcache cache) throws CacheException {
123
132
if (!cache.getCacheConfiguration().isTerracottaClustered()) {
124
LOG.error("You're trying to bootstrap a non Terracotta clustered cache with a TerracottaBootstrapCacheLoader! Cache " +
125
"'{}' will not be bootstrapped and no keySet snapshot will be recorded...", cache.getName());
133
LOG.error("You're trying to bootstrap a non Terracotta clustered cache with a TerracottaBootstrapCacheLoader! Cache "
134
+ "'{}' will not be bootstrapped and no keySet snapshot will be recorded...", cache.getName());
141
150
private void doLoad(final Ehcache cache) {
142
final RotatingSnapshotFile snapshotFile = new RotatingSnapshotFile(directory == null ? cache.getCacheManager()
143
.getDiskStorePath() : directory, cache.getName());
151
CacheManager manager = cache.getCacheManager();
152
if (manager == null) {
153
throw new CacheException("Cache must belong to a cache manager to bootstrap");
156
DiskStorePathManager pathManager = diskStorePathManager != null ? diskStorePathManager : cache.getCacheManager()
157
.getDiskStorePathManager();
159
final RotatingSnapshotFile snapshotFile = new RotatingSnapshotFile(pathManager, cache.getName());
145
161
final Set<Object> keys = snapshotFile.readAll();
154
170
LOG.info("Finished loading {} keys (of {} on disk) from previous snapshot for Cache '{}'",
155
new Object[] {Integer.valueOf(loaded), keys.size(), cache.getName()});
171
new Object[] {Integer.valueOf(loaded), keys.size(), cache.getName()});
156
172
} catch (IOException e) {
157
173
LOG.error("Couldn't load keySet for Cache '{}'", cache.getName(), e);
186
202
keySnapshotter.dispose(immediateShutdown);
205
if (diskStorePathManager != null) {
206
diskStorePathManager.releaseLock();
192
211
* Calling this method will result in a snapshot being taken or wait for the one in progress to finish
193
213
* @throws IOException On exception being thrown while doing the snapshot
195
215
public void doLocalKeySnapshot() throws IOException {