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.util.concurrent.locks.Lock;
20 import java.util.concurrent.locks.ReentrantLock;
21
22 import net.sf.ehcache.pool.Pool;
23 import net.sf.ehcache.pool.PoolableStore;
24 import net.sf.ehcache.pool.Role;
25 import net.sf.ehcache.pool.SizeOfEngine;
26
27 /***
28 * The PoolAccessor class of the StrictlyBoundedPool
29 *
30 * @author Ludovic Orban
31 */
32 final class LockedPoolAccessor extends AbstractPoolAccessor<PoolableStore> {
33
34 private final SizeOfEngine sizeOfEngine;
35 private long size;
36 private final Lock lock = new ReentrantLock();
37
38 /***
39 * Creates a locked pool accessor with the specified properties.
40 *
41 * @param pool pool to be accessed
42 * @param store accessing store
43 * @param sizeOfEngine engine used to size objects
44 * @param currentSize initial size of the store
45 */
46 LockedPoolAccessor(Pool pool, PoolableStore store, SizeOfEngine sizeOfEngine, long currentSize) {
47 super(pool, store);
48 this.sizeOfEngine = sizeOfEngine;
49 this.size = currentSize;
50 }
51
52 /***
53 * {@inheritDoc}
54 */
55 public long add(Object key, Object value, Object container, boolean force) {
56 checkLinked();
57
58 long sizeOf = sizeOfEngine.sizeOf(key, value, container);
59
60
61 lock.lock();
62 try {
63 while (true) {
64 long newSize = getPool().getSize() + sizeOf;
65
66 if (newSize <= getPool().getMaxSize()) {
67
68 size += sizeOf;
69 return sizeOf;
70 } else {
71
72 if (!force && sizeOf > getPool().getMaxSize()) {
73
74 return -1;
75 }
76
77
78 long missingSize = newSize - getPool().getMaxSize();
79
80
81 lock.unlock();
82 try {
83 boolean successful = getPool().getEvictor().freeSpace(getPool().getPoolableStores(), missingSize);
84 if (!force && !successful) {
85
86 return -1;
87 }
88 } finally {
89 lock.lock();
90 }
91
92
93
94 if (!force && getPool().getSize() + sizeOf > getPool().getMaxSize()) {
95 continue;
96 }
97
98 size += sizeOf;
99 return sizeOf;
100 }
101 }
102 } finally {
103 lock.unlock();
104 }
105 }
106
107 /***
108 * {@inheritDoc}
109 */
110 public boolean canAddWithoutEvicting(Object key, Object value, Object container) {
111 long sizeOf = sizeOfEngine.sizeOf(key, value, container);
112
113 lock.lock();
114 try {
115 long newSize = getPool().getSize() + sizeOf;
116 return newSize <= getPool().getMaxSize();
117 } finally {
118 lock.unlock();
119 }
120 }
121
122 /***
123 * {@inheritDoc}
124 */
125 public long delete(Object key, Object value, Object container) {
126 checkLinked();
127
128 long sizeOf = sizeOfEngine.sizeOf(key, value, container);
129
130
131 lock.lock();
132 try {
133 size -= sizeOf;
134 } finally {
135 lock.unlock();
136 }
137
138 return sizeOf;
139 }
140
141 /***
142 * {@inheritDoc}
143 */
144 @Override
145 public long replace(Role role, Object current, Object replacement, boolean force) {
146
147 lock.lock();
148 try {
149 return super.replace(role, current, replacement, force);
150 } finally {
151 lock.unlock();
152 }
153 }
154
155 /***
156 * {@inheritDoc}
157 */
158 public long getSize() {
159
160 lock.lock();
161 try {
162 return size;
163 } finally {
164 lock.unlock();
165 }
166 }
167
168 /***
169 * {@inheritDoc}
170 */
171 public void clear() {
172
173 lock.lock();
174 try {
175 size = 0L;
176 } finally {
177 lock.unlock();
178 }
179 }
180 }