View Javadoc

1   /*
2    * $Id: MuleObjectStoreManager.java 22665 2011-08-15 06:33:46Z mike.schilling $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
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             // Using synchronization here in order to avoid initialising the
141             // monitored object store wrapper for nothing and having to dispose
142             // or putting an uninitialised ObjectStore
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                 //there is nothing we can do                
259             }
260         }
261     }
262 }