View Javadoc

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.pool.impl;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.net.MalformedURLException;
22  import java.net.URL;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.List;
26  
27  import net.sf.ehcache.CacheException;
28  import net.sf.ehcache.pool.SizeOfEngine;
29  import net.sf.ehcache.pool.sizeof.AgentSizeOf;
30  import net.sf.ehcache.pool.sizeof.ReflectionSizeOf;
31  import net.sf.ehcache.pool.sizeof.SizeOf;
32  import net.sf.ehcache.pool.sizeof.UnsafeSizeOf;
33  import net.sf.ehcache.pool.sizeof.filter.AnnotationSizeOfFilter;
34  import net.sf.ehcache.pool.sizeof.filter.CombinationSizeOfFilter;
35  import net.sf.ehcache.pool.sizeof.filter.ResourceSizeOfFilter;
36  import net.sf.ehcache.pool.sizeof.filter.SizeOfFilter;
37  import net.sf.ehcache.util.ClassLoaderUtil;
38  
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  /***
43   * @author Alex Snaps
44   */
45  public class DefaultSizeOfEngine implements SizeOfEngine {
46  
47      private static final Logger LOG = LoggerFactory.getLogger(DefaultSizeOfEngine.class.getName());
48      private static final String USER_FILTER_RESOURCE = "net.sf.ehcache.sizeof.filter";
49  
50      private static final SizeOfFilter DEFAULT_FILTER;
51      static {
52          Collection<SizeOfFilter> filters = new ArrayList<SizeOfFilter>();
53          filters.add(new AnnotationSizeOfFilter());
54          try {
55              filters.add(new ResourceSizeOfFilter(SizeOfEngine.class.getResource("builtin-sizeof.filter")));
56          } catch (IOException e) {
57              LOG.warn("Built-in sizeof filter could not be loaded: {}", e);
58          }
59          SizeOfFilter userFilter = getUserFilter();
60          if (userFilter != null) {
61              filters.add(getUserFilter());
62          }
63          DEFAULT_FILTER = new CombinationSizeOfFilter(filters.toArray(new SizeOfFilter[filters.size()]));
64      }
65  
66      private final SizeOf sizeOf;
67  
68      /***
69       * Creates a default size of engine using the best available sizing algorithm.
70       */
71      public DefaultSizeOfEngine() {
72          SizeOf bestSizeOf;
73          try {
74              bestSizeOf = new AgentSizeOf(DEFAULT_FILTER);
75              LOG.info("using Agent sizeof engine");
76          } catch (UnsupportedOperationException e) {
77              try {
78                  bestSizeOf = new UnsafeSizeOf(DEFAULT_FILTER);
79                  LOG.info("using Unsafe sizeof engine");
80              } catch (UnsupportedOperationException f) {
81                  try {
82                      bestSizeOf = new ReflectionSizeOf(DEFAULT_FILTER);
83                      LOG.info("using Reflection sizeof engine");
84                  } catch (UnsupportedOperationException g) {
85                      throw new CacheException("A suitable SizeOf engine could not be loaded: " + e + ", " + f + ", " + g);
86                  }
87              }
88          }
89  
90          this.sizeOf = bestSizeOf;
91      }
92  
93      private static SizeOfFilter getUserFilter() {
94          String userFilterProperty = System.getProperty(USER_FILTER_RESOURCE);
95  
96          if (userFilterProperty != null) {
97              List<URL> filterUrls = new ArrayList<URL>();
98              try {
99                  filterUrls.add(new URL(userFilterProperty));
100             } catch (MalformedURLException e) {
101                 LOG.debug("MalformedURLException using {} as a URL", userFilterProperty);
102             }
103             try {
104                 filterUrls.add(new File(userFilterProperty).toURI().toURL());
105             } catch (MalformedURLException e) {
106                 LOG.debug("MalformedURLException using {} as a file URL", userFilterProperty);
107             }
108             filterUrls.add(ClassLoaderUtil.getStandardClassLoader().getResource(USER_FILTER_RESOURCE));
109             for (URL filterUrl : filterUrls) {
110                 SizeOfFilter filter;
111                 try {
112                     filter = new ResourceSizeOfFilter(filterUrl);
113                     LOG.info("Using user supplied filter @ {}", filterUrl);
114                     return filter;
115                 } catch (IOException e) {
116                     LOG.debug("IOException while loading user size-of filter resource", e);
117                 }
118             }
119         }
120         return null;
121     }
122 
123     /***
124      * {@inheritDoc}
125      */
126     public long sizeOf(final Object key, final Object value, final Object container) {
127         long size = sizeOf.deepSizeOf(key, value, container);
128         LOG.debug("size of {}/{}/{} -> {}", new Object[]{key, value, container, size});
129         return size;
130     }
131 }