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