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