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 try {
314 completeLatch.await();
315 }
316 catch (InterruptedException ie) {
317 throw processException(ie);
318 }
319
320
321
322 return _competeIncrement(counterRegister, size);
323 }
324
325
326
327 try {
328
329
330
331 counterHolder = counterRegister.getCounterHolder();
332 newValue = counterHolder.addAndGet(size);
333
334 if (newValue > counterHolder.getRangeMax()) {
335 CounterHolder newCounterHolder = _obtainIncrement(
336 counterRegister.getName(), counterRegister.getRangeSize(),
337 0);
338
339 newValue = newCounterHolder.addAndGet(size);
340
341 counterRegister.setCounterHolder(newCounterHolder);
342 }
343 }
344 catch (Exception e) {
345 throw processException(e);
346 }
347 finally {
348
349
350
351 completeLatch.done();
352 }
353
354 return newValue;
355 }
356
357 private CounterHolder _obtainIncrement(
358 String counterName, long range, long size)
359 throws SystemException {
360
361 Session session = null;
362
363 try {
364 session = openSession();
365
366 Counter counter = (Counter)session.get(
367 CounterImpl.class, counterName, LockMode.UPGRADE);
368
369 long newValue = counter.getCurrentId();
370
371 if (size > newValue) {
372 newValue = size;
373 }
374
375 long rangeMax = newValue + range;
376
377 counter.setCurrentId(rangeMax);
378
379 CounterHolder counterHolder = new CounterHolder(newValue, rangeMax);
380
381 session.saveOrUpdate(counter);
382
383 session.flush();
384
385 return counterHolder;
386 }
387 catch (Exception e) {
388 throw processException(e);
389 }
390 finally {
391 closeSession(session);
392 }
393 }
394
395 private static final int _DEFAULT_CURRENT_ID = 0;
396
397 private static final int _MINIMUM_INCREMENT_SIZE = 1;
398
399 private static final String _NAME = Counter.class.getName();
400
401 private static final String _SQL_INSERT =
402 "insert into Counter(name, currentId) values (?, ?)";
403
404 private static final String _SQL_SELECT_ID_BY_NAME =
405 "select currentId from Counter where name = ?";
406
407 private static final String _SQL_SELECT_NAMES =
408 "select name from Counter order by name asc";
409
410 private static final String _SQL_UPDATE_NAME_BY_NAME =
411 "update Counter set name = ? where name = ?";
412
413 private Map<String, CounterRegister> _counterRegisterMap =
414 new ConcurrentHashMap<String, CounterRegister>();
415 private Map<String, Integer> _rangeSizeMap =
416 new ConcurrentHashMap<String, Integer>();
417
418 }