1
14
15 package com.liferay.counter.service.persistence;
16
17 import com.liferay.counter.model.Counter;
18 import com.liferay.counter.model.CounterHolder;
19 import com.liferay.counter.model.CounterRegister;
20 import com.liferay.counter.model.impl.CounterImpl;
21 import com.liferay.portal.kernel.concurrent.CompeteLatch;
22 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
23 import com.liferay.portal.kernel.dao.orm.LockMode;
24 import com.liferay.portal.kernel.dao.orm.ObjectNotFoundException;
25 import com.liferay.portal.kernel.dao.orm.Session;
26 import com.liferay.portal.kernel.exception.SystemException;
27 import com.liferay.portal.kernel.util.GetterUtil;
28 import com.liferay.portal.kernel.util.PropsKeys;
29 import com.liferay.portal.kernel.util.StringPool;
30 import com.liferay.portal.model.Dummy;
31 import com.liferay.portal.service.persistence.impl.BasePersistenceImpl;
32 import com.liferay.portal.util.PropsUtil;
33 import com.liferay.portal.util.PropsValues;
34
35 import java.sql.Connection;
36 import java.sql.PreparedStatement;
37 import java.sql.ResultSet;
38 import java.sql.SQLException;
39
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.concurrent.ConcurrentHashMap;
44
45
54 public class CounterFinderImpl
55 extends BasePersistenceImpl<Dummy> implements CounterFinder {
56
57 public List<String> getNames() throws SystemException {
58 Connection connection = null;
59 PreparedStatement preparedStatement = null;
60 ResultSet resultSet = null;
61
62 try {
63 connection = getConnection();
64
65 preparedStatement = connection.prepareStatement(_SQL_SELECT_NAMES);
66
67 resultSet = preparedStatement.executeQuery();
68
69 List<String> list = new ArrayList<String>();
70
71 while (resultSet.next()) {
72 list.add(resultSet.getString(1));
73 }
74
75 return list;
76 }
77 catch (SQLException sqle) {
78 throw processException(sqle);
79 }
80 finally {
81 DataAccess.cleanUp(connection, preparedStatement, resultSet);
82 }
83 }
84
85 public long increment() throws SystemException {
86 return increment(_NAME);
87 }
88
89 public long increment(String name) throws SystemException {
90 return increment(name, _MINIMUM_INCREMENT_SIZE);
91 }
92
93 public long increment(String name, int size) throws SystemException {
94 if (size < _MINIMUM_INCREMENT_SIZE) {
95 size = _MINIMUM_INCREMENT_SIZE;
96 }
97
98 CounterRegister counterRegister = getCounterRegister(name);
99
100 return _competeIncrement(counterRegister, size);
101 }
102
103 public void rename(String oldName, String newName) throws SystemException {
104 CounterRegister counterRegister = getCounterRegister(oldName);
105
106 synchronized (counterRegister) {
107 if (_counterRegisterMap.containsKey(newName)) {
108 throw new SystemException(
109 "Cannot rename " + oldName + " to " + newName);
110 }
111
112 Connection connection = null;
113 PreparedStatement preparedStatement = null;
114
115 try {
116 connection = getConnection();
117
118 preparedStatement = connection.prepareStatement(
119 _SQL_UPDATE_NAME_BY_NAME);
120
121 preparedStatement.setString(1, newName);
122 preparedStatement.setString(2, oldName);
123
124 preparedStatement.executeUpdate();
125 }
126 catch (ObjectNotFoundException onfe) {
127 }
128 catch (Exception e) {
129 throw processException(e);
130 }
131 finally {
132 DataAccess.cleanUp(connection, preparedStatement);
133 }
134
135 counterRegister.setName(newName);
136
137 _counterRegisterMap.put(newName, counterRegister);
138 _counterRegisterMap.remove(oldName);
139 }
140 }
141
142 public void reset(String name) throws SystemException {
143 CounterRegister counterRegister = getCounterRegister(name);
144
145 synchronized (counterRegister) {
146 Session session = null;
147
148 try {
149 session = openSession();
150
151 Counter counter = (Counter)session.get(CounterImpl.class, name);
152
153 session.delete(counter);
154
155 session.flush();
156 }
157 catch (ObjectNotFoundException onfe) {
158 }
159 catch (Exception e) {
160 throw processException(e);
161 }
162 finally {
163 closeSession(session);
164 }
165
166 _counterRegisterMap.remove(name);
167 }
168 }
169
170 public void reset(String name, long size) throws SystemException {
171 CounterRegister counterRegister = createCounterRegister(name, size);
172
173 _counterRegisterMap.put(name, counterRegister);
174 }
175
176 protected CounterRegister createCounterRegister(String name)
177 throws SystemException {
178
179 return createCounterRegister(name, -1);
180 }
181
182 protected CounterRegister createCounterRegister(String name, long size)
183 throws SystemException {
184
185 long rangeMin = -1;
186 int rangeSize = getRangeSize(name);
187
188 Connection connection = null;
189 PreparedStatement preparedStatement = null;
190 ResultSet resultSet = null;
191
192 try {
193 connection = getConnection();
194
195 preparedStatement = connection.prepareStatement(
196 _SQL_SELECT_ID_BY_NAME);
197
198 preparedStatement.setString(1, name);
199
200 resultSet = preparedStatement.executeQuery();
201
202 if (!resultSet.next()) {
203 rangeMin = _DEFAULT_CURRENT_ID;
204
205 if (size > rangeMin) {
206 rangeMin = size;
207 }
208
209 resultSet.close();
210 preparedStatement.close();
211
212 preparedStatement = connection.prepareStatement(_SQL_INSERT);
213
214 preparedStatement.setString(1, name);
215 preparedStatement.setLong(2, rangeMin);
216
217 preparedStatement.executeUpdate();
218 }
219 }
220 catch (Exception e) {
221 throw processException(e);
222 }
223 finally {
224 DataAccess.cleanUp(connection, preparedStatement, resultSet);
225 }
226
227 CounterHolder counterHolder = _obtainIncrement(name, rangeSize, size);
228
229 return new CounterRegister(name, counterHolder, rangeSize);
230 }
231
232 protected Connection getConnection() throws SQLException {
233 Connection connection = getDataSource().getConnection();
234
235 return connection;
236 }
237
238 protected CounterRegister getCounterRegister(String name)
239 throws SystemException {
240
241 CounterRegister counterRegister = _counterRegisterMap.get(name);
242
243 if (counterRegister != null) {
244 return counterRegister;
245 }
246 else {
247 synchronized (_counterRegisterMap) {
248
249
251 counterRegister = _counterRegisterMap.get(name);
252
253 if (counterRegister == null) {
254 counterRegister = createCounterRegister(name);
255
256 _counterRegisterMap.put(name, counterRegister);
257 }
258
259 return counterRegister;
260 }
261 }
262 }
263
264 protected int getRangeSize(String name) {
265 if (name.equals(_NAME)) {
266 return PropsValues.COUNTER_INCREMENT;
267 }
268
269 String incrementType = null;
270
271 int pos = name.indexOf(StringPool.POUND);
272
273 if (pos != -1) {
274 incrementType = name.substring(0, pos);
275 }
276 else {
277 incrementType = name;
278 }
279
280 Integer rangeSize = _rangeSizeMap.get(incrementType);
281
282 if (rangeSize == null) {
283 rangeSize = GetterUtil.getInteger(
284 PropsUtil.get(
285 PropsKeys.COUNTER_INCREMENT_PREFIX + incrementType),
286 PropsValues.COUNTER_INCREMENT);
287
288 _rangeSizeMap.put(incrementType, rangeSize);
289 }
290
291 return rangeSize.intValue();
292 }
293
294 private long _competeIncrement(CounterRegister counterRegister, int size)
295 throws SystemException {
296
297 CounterHolder counterHolder = counterRegister.getCounterHolder();
298
299
301 long newValue = counterHolder.addAndGet(size);
302
303 if (newValue <= counterHolder.getRangeMax()) {
304 return newValue;
305 }
306
307
309 CompeteLatch completeLatch = counterRegister.getCompeteLatch();
310
311 if (!completeLatch.compete()) {
312
313
315 completeLatch.await();
316
317
319 return _competeIncrement(counterRegister, size);
320 }
321
322
324 try {
325
326
328 counterHolder = counterRegister.getCounterHolder();
329 newValue = counterHolder.addAndGet(size);
330
331 if (newValue > counterHolder.getRangeMax()) {
332 CounterHolder newCounterHolder = _obtainIncrement(
333 counterRegister.getName(), counterRegister.getRangeSize(),
334 0);
335
336 newValue = newCounterHolder.addAndGet(size);
337
338 counterRegister.setCounterHolder(newCounterHolder);
339 }
340 }
341 catch (Exception e) {
342 throw processException(e);
343 }
344 finally {
345
346
348 completeLatch.done();
349 }
350
351 return newValue;
352 }
353
354 private CounterHolder _obtainIncrement(
355 String counterName, long range, long size)
356 throws SystemException {
357
358 Session session = null;
359
360 try {
361 session = openSession();
362
363 Counter counter = (Counter)session.get(
364 CounterImpl.class, counterName, LockMode.UPGRADE);
365
366 long newValue = counter.getCurrentId();
367
368 if (size > newValue) {
369 newValue = size;
370 }
371
372 long rangeMax = newValue + range;
373
374 counter.setCurrentId(rangeMax);
375
376 CounterHolder counterHolder = new CounterHolder(newValue, rangeMax);
377
378 session.saveOrUpdate(counter);
379
380 session.flush();
381
382 return counterHolder;
383 }
384 catch (Exception e) {
385 throw processException(e);
386 }
387 finally {
388 closeSession(session);
389 }
390 }
391
392 private static final int _DEFAULT_CURRENT_ID = 0;
393
394 private static final int _MINIMUM_INCREMENT_SIZE = 1;
395
396 private static final String _NAME = Counter.class.getName();
397
398 private static final String _SQL_INSERT =
399 "insert into Counter(name, currentId) values (?, ?)";
400
401 private static final String _SQL_SELECT_ID_BY_NAME =
402 "select currentId from Counter where name = ?";
403
404 private static final String _SQL_SELECT_NAMES =
405 "select name from Counter order by name asc";
406
407 private static final String _SQL_UPDATE_NAME_BY_NAME =
408 "update Counter set name = ? where name = ?";
409
410 private Map<String, CounterRegister> _counterRegisterMap =
411 new ConcurrentHashMap<String, CounterRegister>();
412 private Map<String, Integer> _rangeSizeMap =
413 new ConcurrentHashMap<String, Integer>();
414
415 }