View Javadoc
1   /**
2    * This file Copyright (c) 2010-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.cache.mbean;
35  
36  import info.magnolia.cms.util.MBeanUtil;
37  import info.magnolia.commands.CommandsManager;
38  import info.magnolia.commands.chain.Command;
39  import info.magnolia.context.Context;
40  import info.magnolia.context.SimpleContext;
41  import info.magnolia.context.SystemContext;
42  import info.magnolia.module.cache.Cache;
43  import info.magnolia.module.cache.CacheFactory;
44  import info.magnolia.module.cache.cachekey.DefaultCacheKey;
45  import info.magnolia.module.cache.cachepolicy.Default;
46  import info.magnolia.module.cache.inject.CacheFactoryProvider;
47  
48  import java.util.HashMap;
49  import java.util.Map;
50  
51  import javax.inject.Inject;
52  import javax.inject.Singleton;
53  
54  /**
55   * <code>MBean</code> implementation for the cache status.
56   */
57  @Singleton
58  public class CacheMonitor implements CacheMonitorMBean {
59  
60      private final CommandsManager commandsManager;
61      private final CacheFactoryProvider cacheFactoryProvider;
62      private final SystemContext systemContext;
63  
64      private int start;
65      private int stop;
66      private Map<String, Integer> calls = new HashMap<String, Integer>();
67      private Map<String, Integer> caches = new HashMap<String, Integer>();
68      private Map<String, Integer> domains = new HashMap<String, Integer>();
69  
70  
71      @Inject
72      public CacheMonitor(CommandsManager commandsManager, CacheFactoryProvider cacheFactoryProvider, SystemContext systemContext) {
73          MBeanUtil.registerMBean("CacheMonitor", this);
74          this.commandsManager = commandsManager;
75          this.cacheFactoryProvider = cacheFactoryProvider;
76          this.systemContext = systemContext;
77      }
78  
79      private Command getCommand(String commandName) {
80          Command flush = commandsManager.getCommand("cache", commandName);
81          if (flush == null) {
82              // TODO: why does it happen that commands are not ready?
83              commandsManager.reload();
84              flush = commandsManager.getCommand("cache", commandName);
85          }
86          if (flush == null) {
87              throw new RuntimeException("Failed to invoke cache " + commandName + " command");
88          }
89          return flush;
90      }
91  
92      public void countStart() {
93          start++;
94      }
95  
96      public void stop() {
97          stop++;
98      }
99  
100     /**
101      * @param name
102      */
103     public void logBehavior(String name) {
104         Integer count = calls.get(name);
105         calls.put(name, count == null ? 1 : ++count);
106     }
107 
108     public void countFlush(String name) {
109         caches.put(name, caches.get(name) == null ? 1 : caches.get(name) + 1);
110     }
111 
112     public void addCache(String name) {
113         caches.put(name, 0);
114     }
115 
116     public void logAccess(Object cacheKey) {
117         if (cacheKey == null || !(cacheKey instanceof DefaultCacheKey)) {
118             return;
119         }
120         DefaultCacheKey key = (DefaultCacheKey) cacheKey;
121         Integer count = this.domains.get(key.getDomain());
122         this.domains.put(key.getDomain(), count == null ? 1 : ++count);
123     }
124 
125     // mbean exposed operations
126     @Override
127     public void flushAll() throws Exception {
128         Command flush = getCommand("flushAll");
129         flush.execute(systemContext);
130     }
131 
132     @Override
133     public void flushByUUID(String repository, String uuid) throws Exception {
134         Command flush = getCommand("flushByUUID");
135         Context ctx = new SimpleContext(systemContext);
136         ctx.put("repository", repository);
137         ctx.put("uuid", uuid);
138         flush.execute(ctx);
139     }
140 
141     // mbean exposed attributes
142     @Override
143     public Map<String, Integer> getAll() {
144         return calls;
145     }
146 
147     @Override
148     public int getHits() {
149         return calls.get("useCache");
150     }
151 
152     @Override
153     public int getBypasses() {
154         return calls.get("bypass");
155     }
156 
157     @Override
158     public int getPuts() {
159         return calls.get("store");
160     }
161 
162     @Override
163     public int getStopCalls() {
164         return stop;
165     }
166 
167     @Override
168     public int getStartCalls() {
169         return start;
170     }
171 
172     @Override
173     public Map<String, Integer> getFlushes() {
174         return caches;
175     }
176 
177     @Override
178     public Map<String, Integer> getDomainAccesses() {
179         return domains;
180     }
181 
182     @Override
183     public int getCachedKeysCount() {
184         int count = 0;
185         // there's most likely gonna be ever just one map in the default cache, but let's not assume that and search all configured caches
186         CacheFactory factory = cacheFactoryProvider.get();
187         for (String name : caches.keySet()) {
188             // skip the uuid-key cache itself
189             if (Default.UUID_KEY_MAP_KEY.equals(name)) {
190                 continue;
191             }
192             Cache cache = factory.getCache(name);
193             count += cache.getSize();
194         }
195         return count;
196     }
197 
198     @Override
199     public int getCachedUUIDsCount() {
200         CacheFactory factory = cacheFactoryProvider.get();
201         Cache cache = factory.getCache(Default.UUID_KEY_MAP_KEY);
202         return cache.getSize();
203     }
204 }