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