1 /***
2 * Copyright 2003-2010 Terracotta, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package net.sf.ehcache.distribution;
18
19 import net.sf.ehcache.event.CacheEventListener;
20 import net.sf.ehcache.event.CacheEventListenerFactory;
21 import net.sf.ehcache.util.PropertyUtil;
22
23 import java.util.Properties;
24
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28
29 /***
30 * Creates an RMICacheReplicator using properties. Config lines look like:
31 * <pre><cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
32 * properties="
33 * replicateAsynchronously=true,
34 * replicatePuts=true
35 * replicateUpdates=true
36 * replicateUpdatesViaCopy=true
37 * replicateRemovals=true
38 * "/></pre>
39 *
40 * @author <a href="mailto:gluck@thoughtworks.com">Greg Luck</a>
41 * @version $Id: RMICacheReplicatorFactory.html 13146 2011-08-01 17:12:39Z oletizi $
42 */
43 public class RMICacheReplicatorFactory extends CacheEventListenerFactory {
44
45 /***
46 * A default for the amount of time the replication thread sleeps after it detects the replicationQueue is empty
47 * before checking again.
48 */
49 protected static final int DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS = 1000;
50
51 private static final Logger LOG = LoggerFactory.getLogger(RMICacheReplicatorFactory.class.getName());
52 private static final String REPLICATE_PUTS = "replicatePuts";
53 private static final String REPLICATE_PUTS_VIA_COPY = "replicatePutsViaCopy";
54 private static final String REPLICATE_UPDATES = "replicateUpdates";
55 private static final String REPLICATE_UPDATES_VIA_COPY = "replicateUpdatesViaCopy";
56 private static final String REPLICATE_REMOVALS = "replicateRemovals";
57 private static final String REPLICATE_ASYNCHRONOUSLY = "replicateAsynchronously";
58 private static final String ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS = "asynchronousReplicationIntervalMillis";
59 private static final int MINIMUM_REASONABLE_INTERVAL = 10;
60
61 /***
62 * Create a <code>CacheEventListener</code> which is also a CacheReplicator.
63 * <p/>
64 * The defaults if properties are not specified are:
65 * <ul>
66 * <li>replicatePuts=true
67 * <li>replicatePutsViaCopy=true
68 * <li>replicateUpdates=true
69 * <li>replicateUpdatesViaCopy=true
70 * <li>replicateRemovals=true;
71 * <li>replicateAsynchronously=true
72 * <li>asynchronousReplicationIntervalMillis=1000
73 * </ul>
74 *
75 * @param properties implementation specific properties. These are configured as comma
76 * separated name value pairs in ehcache.xml e.g.
77 * <p/>
78 * <code>
79 * <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
80 * properties="
81 * replicateAsynchronously=true,
82 * replicatePuts=true
83 * replicateUpdates=true
84 * replicateUpdatesViaCopy=true
85 * replicateRemovals=true
86 * asynchronousReplicationIntervalMillis=1000
87 * "/></code>
88 * @return a constructed CacheEventListener
89 */
90 public final CacheEventListener createCacheEventListener(Properties properties) {
91 boolean replicatePuts = extractReplicatePuts(properties);
92 boolean replicatePutsViaCopy = extractReplicatePutsViaCopy(properties);
93 boolean replicateUpdates = extractReplicateUpdates(properties);
94 boolean replicateUpdatesViaCopy = extractReplicateUpdatesViaCopy(properties);
95 boolean replicateRemovals = extractReplicateRemovals(properties);
96 boolean replicateAsynchronously = extractReplicateAsynchronously(properties);
97 int asynchronousReplicationIntervalMillis = extractReplicationIntervalMilis(properties);
98
99 if (replicateAsynchronously) {
100 return new RMIAsynchronousCacheReplicator(
101 replicatePuts,
102 replicatePutsViaCopy,
103 replicateUpdates,
104 replicateUpdatesViaCopy,
105 replicateRemovals,
106 asynchronousReplicationIntervalMillis);
107 } else {
108 return new RMISynchronousCacheReplicator(
109 replicatePuts,
110 replicatePutsViaCopy,
111 replicateUpdates,
112 replicateUpdatesViaCopy,
113 replicateRemovals);
114 }
115 }
116
117 /***
118 * Extracts the value of asynchronousReplicationIntervalMillis. Sets it to 1000ms if
119 * either not set or there is a problem parsing the number
120 * @param properties
121 */
122 protected int extractReplicationIntervalMilis(Properties properties) {
123 int asynchronousReplicationIntervalMillis;
124 String asynchronousReplicationIntervalMillisString =
125 PropertyUtil.extractAndLogProperty(ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS, properties);
126 if (asynchronousReplicationIntervalMillisString != null) {
127 try {
128 int asynchronousReplicationIntervalMillisCandidate =
129 Integer.parseInt(asynchronousReplicationIntervalMillisString);
130 if (asynchronousReplicationIntervalMillisCandidate < MINIMUM_REASONABLE_INTERVAL) {
131 LOG.debug("Trying to set the asynchronousReplicationIntervalMillis to an unreasonable number." +
132 " Using the default instead.");
133 asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
134 } else {
135 asynchronousReplicationIntervalMillis = asynchronousReplicationIntervalMillisCandidate;
136 }
137 } catch (NumberFormatException e) {
138 LOG.warn("Number format exception trying to set asynchronousReplicationIntervalMillis. " +
139 "Using the default instead. String value was: '" + asynchronousReplicationIntervalMillisString + "'");
140 asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
141 }
142 } else {
143 asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
144 }
145 return asynchronousReplicationIntervalMillis;
146 }
147
148 /***
149 * Extracts the value of replicateAsynchronously from the properties
150 * @param properties
151 */
152 protected boolean extractReplicateAsynchronously(Properties properties) {
153 boolean replicateAsynchronously;
154 String replicateAsynchronouslyString = PropertyUtil.extractAndLogProperty(REPLICATE_ASYNCHRONOUSLY, properties);
155 if (replicateAsynchronouslyString != null) {
156 replicateAsynchronously = PropertyUtil.parseBoolean(replicateAsynchronouslyString);
157 } else {
158 replicateAsynchronously = true;
159 }
160 return replicateAsynchronously;
161 }
162
163 /***
164 * Extracts the value of replicateRemovals from the properties
165 * @param properties
166 */
167 protected boolean extractReplicateRemovals(Properties properties) {
168 boolean replicateRemovals;
169 String replicateRemovalsString = PropertyUtil.extractAndLogProperty(REPLICATE_REMOVALS, properties);
170 if (replicateRemovalsString != null) {
171 replicateRemovals = PropertyUtil.parseBoolean(replicateRemovalsString);
172 } else {
173 replicateRemovals = true;
174 }
175 return replicateRemovals;
176 }
177
178 /***
179 * Extracts the value of replicateUpdatesViaCopy from the properties
180 * @param properties
181 */
182 protected boolean extractReplicateUpdatesViaCopy(Properties properties) {
183 boolean replicateUpdatesViaCopy;
184 String replicateUpdatesViaCopyString = PropertyUtil.extractAndLogProperty(REPLICATE_UPDATES_VIA_COPY, properties);
185 if (replicateUpdatesViaCopyString != null) {
186 replicateUpdatesViaCopy = PropertyUtil.parseBoolean(replicateUpdatesViaCopyString);
187 } else {
188 replicateUpdatesViaCopy = true;
189 }
190 return replicateUpdatesViaCopy;
191 }
192
193 /***
194 * Extracts the value of replicatePutsViaCopy from the properties
195 * @param properties
196 */
197 protected boolean extractReplicatePutsViaCopy(Properties properties) {
198 boolean replicatePutsViaCopy;
199 String replicatePutsViaCopyString = PropertyUtil.extractAndLogProperty(REPLICATE_PUTS_VIA_COPY, properties);
200 if (replicatePutsViaCopyString != null) {
201 replicatePutsViaCopy = PropertyUtil.parseBoolean(replicatePutsViaCopyString);
202 } else {
203 replicatePutsViaCopy = true;
204 }
205 return replicatePutsViaCopy;
206 }
207
208 /***
209 * Extracts the value of replicateUpdates from the properties
210 * @param properties
211 */
212 protected boolean extractReplicateUpdates(Properties properties) {
213 boolean replicateUpdates;
214 String replicateUpdatesString = PropertyUtil.extractAndLogProperty(REPLICATE_UPDATES, properties);
215 if (replicateUpdatesString != null) {
216 replicateUpdates = PropertyUtil.parseBoolean(replicateUpdatesString);
217 } else {
218 replicateUpdates = true;
219 }
220 return replicateUpdates;
221 }
222
223 /***
224 * Extracts the value of replicatePuts from the properties
225 * @param properties
226 */
227 protected boolean extractReplicatePuts(Properties properties) {
228 boolean replicatePuts;
229 String replicatePutsString = PropertyUtil.extractAndLogProperty(REPLICATE_PUTS, properties);
230 if (replicatePutsString != null) {
231 replicatePuts = PropertyUtil.parseBoolean(replicatePutsString);
232 } else {
233 replicatePuts = true;
234 }
235 return replicatePuts;
236 }
237
238
239 }