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 net.sf.ehcache.pool.PoolEvictor;
20  import net.sf.ehcache.pool.PoolableStore;
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  
25  /***
26   * Abstract pool evictor which always evicts from the store consuming the most resources.
27   *
28   * @author Ludovic Orban
29   */
30  public abstract class AbstractFromLargestCachePoolEvictor implements PoolEvictor<PoolableStore> {
31  
32      /***
33       * {@inheritDoc}
34       */
35      public boolean freeSpace(Collection<PoolableStore> from, long bytes) {
36          if (from == null || from.isEmpty()) {
37              return false;
38          }
39  
40          long remainingSizeInBytes = bytes;
41          Collection<PoolableStore> tried = new ArrayList<PoolableStore>();
42  
43          while (tried.size() != from.size()) {
44              PoolableStore largestPoolableStore = findUntriedLargestPoolableStore(from, tried);
45  
46              long beforeEvictionSize = getSizeInBytes(largestPoolableStore);
47              if (!evict(1, bytes, largestPoolableStore)) {
48                  tried.add(largestPoolableStore);
49                  continue;
50              }
51              long afterEvictionSize = getSizeInBytes(largestPoolableStore);
52  
53              remainingSizeInBytes -= (beforeEvictionSize - afterEvictionSize);
54              if (remainingSizeInBytes <= 0L) {
55                  return true;
56              }
57          }
58  
59          return false;
60      }
61  
62      /***
63       * Evict from a store for a chosen resource
64       *
65       * @param count the element count
66       * @param bytes the bytes count
67       * @param poolableStore the store
68       * @return true if eviction succeeded, ie: if there was enough evictable resource held by the store
69       */
70      protected abstract boolean evict(int count, long bytes, PoolableStore poolableStore);
71  
72      /***
73       * Get a store size in bytes for a chosen resource
74       *
75       * @param poolableStore the store
76       * @return the size in bytes
77       */
78      protected abstract long getSizeInBytes(PoolableStore poolableStore);
79  
80      private PoolableStore findUntriedLargestPoolableStore(Collection<PoolableStore> from, Collection<PoolableStore> tried) {
81          PoolableStore largestPoolableStore = null;
82          for (PoolableStore poolableStore : from) {
83              if (alreadyTried(tried, poolableStore)) {
84                  continue;
85              }
86  
87              if (largestPoolableStore == null || getSizeInBytes(poolableStore) > getSizeInBytes(largestPoolableStore)) {
88                  largestPoolableStore = poolableStore;
89              }
90          }
91          return largestPoolableStore;
92      }
93  
94      private boolean alreadyTried(Collection<PoolableStore> tried, PoolableStore from) {
95          for (PoolableStore poolableStore : tried) {
96              if (poolableStore == from) {
97                  return true;
98              }
99          }
100         return false;
101     }
102 
103 }