001
014
015 package com.liferay.counter.service.persistence;
016
017 import com.liferay.counter.model.Counter;
018 import com.liferay.counter.model.CounterHolder;
019 import com.liferay.counter.model.CounterRegister;
020 import com.liferay.counter.model.impl.CounterImpl;
021 import com.liferay.portal.kernel.cache.CacheRegistryItem;
022 import com.liferay.portal.kernel.cache.CacheRegistryUtil;
023 import com.liferay.portal.kernel.concurrent.CompeteLatch;
024 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
025 import com.liferay.portal.kernel.dao.orm.LockMode;
026 import com.liferay.portal.kernel.dao.orm.ObjectNotFoundException;
027 import com.liferay.portal.kernel.dao.orm.Session;
028 import com.liferay.portal.kernel.exception.SystemException;
029 import com.liferay.portal.kernel.util.CharPool;
030 import com.liferay.portal.kernel.util.GetterUtil;
031 import com.liferay.portal.kernel.util.PropsKeys;
032 import com.liferay.portal.model.Dummy;
033 import com.liferay.portal.service.persistence.impl.BasePersistenceImpl;
034 import com.liferay.portal.util.PropsUtil;
035 import com.liferay.portal.util.PropsValues;
036
037 import java.sql.Connection;
038 import java.sql.PreparedStatement;
039 import java.sql.ResultSet;
040 import java.sql.SQLException;
041
042 import java.util.ArrayList;
043 import java.util.List;
044 import java.util.Map;
045 import java.util.concurrent.ConcurrentHashMap;
046
047
054 public class CounterFinderImpl
055 extends BasePersistenceImpl<Dummy>
056 implements CacheRegistryItem, CounterFinder {
057
058 @Override
059 public void afterPropertiesSet() {
060 CacheRegistryUtil.register(this);
061 }
062
063 @Override
064 public List<String> getNames() throws SystemException {
065 Connection connection = null;
066 PreparedStatement preparedStatement = null;
067 ResultSet resultSet = null;
068
069 try {
070 connection = getConnection();
071
072 preparedStatement = connection.prepareStatement(_SQL_SELECT_NAMES);
073
074 resultSet = preparedStatement.executeQuery();
075
076 List<String> list = new ArrayList<String>();
077
078 while (resultSet.next()) {
079 list.add(resultSet.getString(1));
080 }
081
082 return list;
083 }
084 catch (SQLException sqle) {
085 throw processException(sqle);
086 }
087 finally {
088 DataAccess.cleanUp(connection, preparedStatement, resultSet);
089 }
090 }
091
092 @Override
093 public String getRegistryName() {
094 return CounterFinderImpl.class.getName();
095 }
096
097 @Override
098 public long increment() throws SystemException {
099 return increment(_NAME);
100 }
101
102 @Override
103 public long increment(String name) throws SystemException {
104 return increment(name, _MINIMUM_INCREMENT_SIZE);
105 }
106
107 @Override
108 public long increment(String name, int size) throws SystemException {
109 if (size < _MINIMUM_INCREMENT_SIZE) {
110 size = _MINIMUM_INCREMENT_SIZE;
111 }
112
113 CounterRegister counterRegister = getCounterRegister(name);
114
115 return _competeIncrement(counterRegister, size);
116 }
117
118 @Override
119 public void invalidate() {
120 _counterRegisterMap.clear();
121 }
122
123 @Override
124 public void rename(String oldName, String newName) throws SystemException {
125 CounterRegister counterRegister = getCounterRegister(oldName);
126
127 synchronized (counterRegister) {
128 if (_counterRegisterMap.containsKey(newName)) {
129 throw new SystemException(
130 "Cannot rename " + oldName + " to " + newName);
131 }
132
133 Connection connection = null;
134 PreparedStatement preparedStatement = null;
135
136 try {
137 connection = getConnection();
138
139 preparedStatement = connection.prepareStatement(
140 _SQL_UPDATE_NAME_BY_NAME);
141
142 preparedStatement.setString(1, newName);
143 preparedStatement.setString(2, oldName);
144
145 preparedStatement.executeUpdate();
146 }
147 catch (ObjectNotFoundException onfe) {
148 }
149 catch (Exception e) {
150 throw processException(e);
151 }
152 finally {
153 DataAccess.cleanUp(connection, preparedStatement);
154 }
155
156 counterRegister.setName(newName);
157
158 _counterRegisterMap.put(newName, counterRegister);
159 _counterRegisterMap.remove(oldName);
160 }
161 }
162
163 @Override
164 public void reset(String name) throws SystemException {
165 CounterRegister counterRegister = getCounterRegister(name);
166
167 synchronized (counterRegister) {
168 Session session = null;
169
170 try {
171 session = openSession();
172
173 Counter counter = (Counter)session.get(CounterImpl.class, name);
174
175 session.delete(counter);
176
177 session.flush();
178 }
179 catch (ObjectNotFoundException onfe) {
180 }
181 catch (Exception e) {
182 throw processException(e);
183 }
184 finally {
185 closeSession(session);
186 }
187
188 _counterRegisterMap.remove(name);
189 }
190 }
191
192 @Override
193 public void reset(String name, long size) throws SystemException {
194 CounterRegister counterRegister = createCounterRegister(name, size);
195
196 _counterRegisterMap.put(name, counterRegister);
197 }
198
199 protected CounterRegister createCounterRegister(String name)
200 throws SystemException {
201
202 return createCounterRegister(name, -1);
203 }
204
205 protected CounterRegister createCounterRegister(String name, long size)
206 throws SystemException {
207
208 long rangeMin = -1;
209 int rangeSize = getRangeSize(name);
210
211 Connection connection = null;
212 PreparedStatement preparedStatement = null;
213 ResultSet resultSet = null;
214
215 try {
216 connection = getConnection();
217
218 preparedStatement = connection.prepareStatement(
219 _SQL_SELECT_ID_BY_NAME);
220
221 preparedStatement.setString(1, name);
222
223 resultSet = preparedStatement.executeQuery();
224
225 if (!resultSet.next()) {
226 rangeMin = _DEFAULT_CURRENT_ID;
227
228 if (size > rangeMin) {
229 rangeMin = size;
230 }
231
232 resultSet.close();
233 preparedStatement.close();
234
235 preparedStatement = connection.prepareStatement(_SQL_INSERT);
236
237 preparedStatement.setString(1, name);
238 preparedStatement.setLong(2, rangeMin);
239
240 preparedStatement.executeUpdate();
241 }
242 }
243 catch (Exception e) {
244 throw processException(e);
245 }
246 finally {
247 DataAccess.cleanUp(connection, preparedStatement, resultSet);
248 }
249
250 CounterHolder counterHolder = _obtainIncrement(name, rangeSize, size);
251
252 return new CounterRegister(name, counterHolder, rangeSize);
253 }
254
255 protected Connection getConnection() throws SQLException {
256 Connection connection = getDataSource().getConnection();
257
258 return connection;
259 }
260
261 protected CounterRegister getCounterRegister(String name)
262 throws SystemException {
263
264 CounterRegister counterRegister = _counterRegisterMap.get(name);
265
266 if (counterRegister != null) {
267 return counterRegister;
268 }
269
270 synchronized (_counterRegisterMap) {
271
272
273
274 counterRegister = _counterRegisterMap.get(name);
275
276 if (counterRegister == null) {
277 counterRegister = createCounterRegister(name);
278
279 _counterRegisterMap.put(name, counterRegister);
280 }
281
282 return counterRegister;
283 }
284 }
285
286 protected int getRangeSize(String name) {
287 if (name.equals(_NAME)) {
288 return PropsValues.COUNTER_INCREMENT;
289 }
290
291 String incrementType = null;
292
293 int pos = name.indexOf(CharPool.POUND);
294
295 if (pos != -1) {
296 incrementType = name.substring(0, pos);
297 }
298 else {
299 incrementType = name;
300 }
301
302 Integer rangeSize = _rangeSizeMap.get(incrementType);
303
304 if (rangeSize == null) {
305 rangeSize = GetterUtil.getInteger(
306 PropsUtil.get(
307 PropsKeys.COUNTER_INCREMENT_PREFIX + incrementType),
308 PropsValues.COUNTER_INCREMENT);
309
310 _rangeSizeMap.put(incrementType, rangeSize);
311 }
312
313 return rangeSize.intValue();
314 }
315
316 private long _competeIncrement(CounterRegister counterRegister, int size)
317 throws SystemException {
318
319 CounterHolder counterHolder = counterRegister.getCounterHolder();
320
321
322
323 long newValue = counterHolder.addAndGet(size);
324
325 if (newValue <= counterHolder.getRangeMax()) {
326 return newValue;
327 }
328
329
330
331 CompeteLatch completeLatch = counterRegister.getCompeteLatch();
332
333 if (!completeLatch.compete()) {
334
335
336
337 try {
338 completeLatch.await();
339 }
340 catch (InterruptedException ie) {
341 throw processException(ie);
342 }
343
344
345
346 return _competeIncrement(counterRegister, size);
347 }
348
349
350
351 try {
352
353
354
355 counterHolder = counterRegister.getCounterHolder();
356 newValue = counterHolder.addAndGet(size);
357
358 if (newValue > counterHolder.getRangeMax()) {
359 CounterHolder newCounterHolder = _obtainIncrement(
360 counterRegister.getName(), counterRegister.getRangeSize(),
361 0);
362
363 newValue = newCounterHolder.addAndGet(size);
364
365 counterRegister.setCounterHolder(newCounterHolder);
366 }
367 }
368 catch (Exception e) {
369 throw processException(e);
370 }
371 finally {
372
373
374
375 completeLatch.done();
376 }
377
378 return newValue;
379 }
380
381 private CounterHolder _obtainIncrement(
382 String counterName, long range, long size)
383 throws SystemException {
384
385 Session session = null;
386
387 try {
388 session = openSession();
389
390 Counter counter = (Counter)session.get(
391 CounterImpl.class, counterName, LockMode.UPGRADE);
392
393 long newValue = counter.getCurrentId();
394
395 if (size > newValue) {
396 newValue = size;
397 }
398
399 long rangeMax = newValue + range;
400
401 counter.setCurrentId(rangeMax);
402
403 CounterHolder counterHolder = new CounterHolder(newValue, rangeMax);
404
405 session.saveOrUpdate(counter);
406
407 session.flush();
408
409 return counterHolder;
410 }
411 catch (Exception e) {
412 throw processException(e);
413 }
414 finally {
415 closeSession(session);
416 }
417 }
418
419 private static final int _DEFAULT_CURRENT_ID = 0;
420
421 private static final int _MINIMUM_INCREMENT_SIZE = 1;
422
423 private static final String _NAME = Counter.class.getName();
424
425 private static final String _SQL_INSERT =
426 "insert into Counter(name, currentId) values (?, ?)";
427
428 private static final String _SQL_SELECT_ID_BY_NAME =
429 "select currentId from Counter where name = ?";
430
431 private static final String _SQL_SELECT_NAMES =
432 "select name from Counter order by name asc";
433
434 private static final String _SQL_UPDATE_NAME_BY_NAME =
435 "update Counter set name = ? where name = ?";
436
437 private Map<String, CounterRegister> _counterRegisterMap =
438 new ConcurrentHashMap<String, CounterRegister>();
439 private Map<String, Integer> _rangeSizeMap =
440 new ConcurrentHashMap<String, Integer>();
441
442 }