1
2
3
4
5
6
7
8
9
10
11 package org.mule.util.store;
12
13 import org.mule.api.MuleContext;
14 import org.mule.api.MuleRuntimeException;
15 import org.mule.api.config.MuleProperties;
16 import org.mule.api.context.MuleContextAware;
17 import org.mule.api.lifecycle.Disposable;
18 import org.mule.api.lifecycle.Initialisable;
19 import org.mule.api.lifecycle.InitialisationException;
20 import org.mule.api.store.ListableObjectStore;
21 import org.mule.api.store.ObjectStore;
22 import org.mule.api.store.ObjectStoreException;
23 import org.mule.api.store.ObjectStoreManager;
24 import org.mule.api.store.PartitionableExpirableObjectStore;
25 import org.mule.api.store.PartitionableObjectStore;
26 import org.mule.util.concurrent.DaemonThreadFactory;
27
28 import java.io.Serializable;
29 import java.util.List;
30 import java.util.concurrent.ConcurrentHashMap;
31 import java.util.concurrent.ConcurrentMap;
32 import java.util.concurrent.ScheduledThreadPoolExecutor;
33 import java.util.concurrent.TimeUnit;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37
38 public class MuleObjectStoreManager
39 implements ObjectStoreManager, MuleContextAware, Initialisable, Disposable
40 {
41 MuleContext muleContext;
42 ConcurrentMap<String, ObjectStore<?>> stores = new ConcurrentHashMap<String, ObjectStore<?>>();
43 protected ScheduledThreadPoolExecutor scheduler;
44 private static Log logger = LogFactory.getLog(MuleObjectStoreManager.class);
45
46 @Override
47 public <T extends ObjectStore<? extends Serializable>> T getObjectStore(String name)
48 {
49 return this.<T> getObjectStore(name, false);
50 }
51
52 @Override
53 public <T extends ObjectStore<? extends Serializable>> T getObjectStore(String name, boolean isPersistent)
54 {
55 return this.<T> getObjectStore(name, isPersistent, 0, 0, 0);
56 }
57
58 @SuppressWarnings({"unchecked"})
59 synchronized public <T extends ObjectStore<? extends Serializable>> T getObjectStore(String name,
60 boolean isPersistent,
61 int maxEntries,
62 int entryTTL,
63 int expirationInterval)
64 {
65 if (stores.containsKey(name))
66 {
67 return (T) stores.get(name);
68 }
69 ListableObjectStore<?> baseStore;
70 if (isPersistent)
71 {
72 baseStore = (ListableObjectStore<?>) muleContext.getRegistry().lookupObject(
73 MuleProperties.OBJECT_STORE_DEFAULT_PERSISTENT_NAME);
74 }
75 else
76 {
77 baseStore = (ListableObjectStore<?>) muleContext.getRegistry().lookupObject(
78 MuleProperties.OBJECT_STORE_DEFAULT_IN_MEMORY_NAME);
79 }
80 T store=this.<T>getPartitionFromBaseObjectStore(baseStore,name);
81
82 if (maxEntries == 0)
83 {
84 return putInStoreMap(name,store);
85 }
86 else
87 {
88 return getMonitorablePartition(name,baseStore,store,entryTTL,maxEntries,expirationInterval);
89 }
90 }
91
92 @SuppressWarnings({"rawtypes", "unchecked"})
93 private <T extends ObjectStore<? extends Serializable>> T getPartitionFromBaseObjectStore(ListableObjectStore baseStore, String partitionName)
94 {
95 if (baseStore instanceof PartitionableObjectStore)
96 {
97 return (T) new ObjectStorePartition(partitionName, (PartitionableObjectStore) baseStore);
98 }
99 else
100 {
101 return (T) new PartitionedObjectStoreWrapper(partitionName, muleContext, (ListableObjectStore) baseStore);
102 }
103 }
104
105 private <T extends ObjectStore<? extends Serializable>> T putInStoreMap(String name,T store)
106 {
107 @SuppressWarnings("unchecked")
108 T previous = (T) stores.putIfAbsent(name, store);
109 if (previous == null)
110 {
111 return (T) store;
112 }
113 else
114 {
115 return previous;
116 }
117 }
118
119 @SuppressWarnings({"rawtypes", "unchecked"})
120 private <T extends ObjectStore<? extends Serializable>> T getMonitorablePartition(String name,ListableObjectStore baseStore,T store, int entryTTL, int maxEntries, int expirationInterval)
121 {
122 if (baseStore instanceof PartitionableExpirableObjectStore)
123 {
124 T previous = (T) stores.putIfAbsent(name, store);
125 if (previous == null)
126 {
127 Monitor m = new Monitor(name, (PartitionableExpirableObjectStore) baseStore, entryTTL,
128 maxEntries);
129 scheduler.scheduleWithFixedDelay(m, 0, expirationInterval, TimeUnit.MILLISECONDS);
130 return (T) store;
131 }
132 else
133 {
134 return previous;
135 }
136 }
137 else
138 {
139 MonitoredObjectStoreWrapper monObjectStore;
140
141
142
143 synchronized (this)
144 {
145 if (stores.containsKey(name))
146 {
147 return (T) stores.get(name);
148 }
149 monObjectStore = new MonitoredObjectStoreWrapper((ListableObjectStore) store, maxEntries,
150 entryTTL, expirationInterval);
151 monObjectStore.setMuleContext(muleContext);
152 try
153 {
154 monObjectStore.initialise();
155 }
156 catch (InitialisationException e)
157 {
158 throw new MuleRuntimeException(e);
159 }
160 stores.put(name, monObjectStore);
161 }
162 return (T) monObjectStore;
163 }
164 }
165
166 @Override
167 public void setMuleContext(MuleContext context)
168 {
169 this.muleContext = context;
170 }
171
172 public void clearStoreCache()
173 {
174 stores.clear();
175 }
176
177 @Override
178 public void dispose()
179 {
180 scheduler.shutdown();
181 }
182
183 @Override
184 public void initialise() throws InitialisationException
185 {
186 scheduler = new ScheduledThreadPoolExecutor(1);
187 scheduler.setThreadFactory(new DaemonThreadFactory("ObjectStoreManager-Monitor", this.getClass()
188 .getClassLoader()));
189 }
190
191 class Monitor implements Runnable
192 {
193 private final String partitionName;
194 private final PartitionableExpirableObjectStore<? extends Serializable> store;
195 private final int entryTTL;
196 private final int maxEntries;
197
198 public Monitor(String partitionName,
199 PartitionableExpirableObjectStore<? extends Serializable> store,
200 int entryTTL,
201 int maxEntries)
202 {
203 this.partitionName = partitionName;
204 this.store = store;
205 this.entryTTL = entryTTL;
206 this.maxEntries = maxEntries;
207 }
208
209 @Override
210 public void run()
211 {
212 if (muleContext.isPrimaryPollingInstance())
213 {
214 try
215 {
216 store.expire(entryTTL, maxEntries, partitionName);
217 }
218 catch (Exception e)
219 {
220 MuleObjectStoreManager.logger.warn("Running expirty on partition " + partitionName + " of "
221 + store + " threw " + e + ":" + e.getMessage());
222 }
223 }
224 }
225
226 }
227
228 @Override
229 public void disposeStore(ObjectStore<? extends Serializable> store) throws ObjectStoreException
230 {
231 if(store instanceof ObjectStorePartition)
232 {
233 ObjectStorePartition partition=(ObjectStorePartition)store;
234 partition.getBaseStore().disposePartition(partition.getPartitionName());
235 }
236 else
237 {
238 if(store instanceof ListableObjectStore)
239 {
240 ListableObjectStore listableStore=(ListableObjectStore)store;
241 while(true)
242 {
243 List<Serializable> keys=listableStore.allKeys();
244 if(keys.size()==0)
245 {
246 break;
247 }else
248 {
249 for(Serializable key:keys)
250 {
251 listableStore.remove(key);
252 }
253 }
254 }
255 }
256 else
257 {
258
259 }
260 }
261 }
262 }