/src/main/java/com/google/ie/business/service/impl/ShardedCounterServiceImpl.java

http://thoughtsite.googlecode.com/ · Java · 267 lines · 191 code · 39 blank · 37 comment · 35 complexity · c2eaed2bb3bd13dbb6e94c0690e80940 MD5 · raw file

  1. /* Copyright 2010 Google Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS.
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License
  14. */
  15. package com.google.ie.business.service.impl;
  16. import com.google.ie.business.dao.ShardedCounterDao;
  17. import com.google.ie.business.dao.impl.DaoConstants;
  18. import com.google.ie.business.domain.ShardedCounter;
  19. import com.google.ie.business.service.IdeaService;
  20. import com.google.ie.business.service.ServiceConstants;
  21. import com.google.ie.business.service.ShardedCounterService;
  22. import com.google.ie.common.cache.CacheConstants;
  23. import com.google.ie.common.cache.CacheHelper;
  24. import org.apache.log4j.Logger;
  25. import org.springframework.beans.factory.annotation.Autowired;
  26. import org.springframework.stereotype.Service;
  27. import org.springframework.transaction.annotation.Propagation;
  28. import org.springframework.transaction.annotation.Transactional;
  29. import java.util.List;
  30. import java.util.Random;
  31. /**
  32. * A service implementation of the {@link ShardedCounterService}.
  33. *
  34. * @author gmaurya
  35. *
  36. */
  37. @Service
  38. public class ShardedCounterServiceImpl implements ShardedCounterService {
  39. private static Logger logger = Logger.getLogger(ShardedCounterServiceImpl.class);
  40. @Autowired
  41. private ShardedCounterDao shardedCounterDao;
  42. @Autowired
  43. private IdeaService ideaService;
  44. public IdeaService getIdeaService() {
  45. return ideaService;
  46. }
  47. public void setIdeaService(IdeaService ideaService) {
  48. this.ideaService = ideaService;
  49. }
  50. private static final int CACHEDELAY = 120;
  51. @Override
  52. public ShardedCounter getMergedShardedCounter(String parentKey) {
  53. logger.debug("Getting Merged sharded counter for parent key : " + parentKey);
  54. if (parentKey == null)
  55. return null;
  56. Object obj = CacheHelper.getObject(CacheConstants.IDEA_SHARD_NAMESPACE, parentKey);
  57. ShardedCounter shardedCounter = null;
  58. if (obj != null && obj instanceof ShardedCounter) {
  59. shardedCounter = (ShardedCounter) obj;
  60. }
  61. // Retrieve merged sharded counter from datastore
  62. if (shardedCounter == null) {
  63. shardedCounter = new ShardedCounter(parentKey);
  64. List<ShardedCounter> shards = shardedCounterDao.getShardsByParentKey(parentKey);
  65. if (shards != null && !shards.isEmpty()) {
  66. for (ShardedCounter shard : shards) {
  67. shardedCounter.setTotalPoint(shard.getTotalPoint()
  68. + shardedCounter.getTotalPoint());
  69. shardedCounter.setNegativePoint(shard.getNegativePoint()
  70. + shardedCounter.getNegativePoint());
  71. shardedCounter.setPositivePoint(shard.getPositivePoint()
  72. + shardedCounter.getPositivePoint());
  73. }
  74. }
  75. CacheHelper.putObject(CacheConstants.IDEA_SHARD_NAMESPACE, parentKey, shardedCounter,
  76. CACHEDELAY);
  77. }
  78. return shardedCounter;
  79. }
  80. @Override
  81. public int getNegativePoint(String parentKey) {
  82. logger.debug("Getting negative point count from sharded counter for parent key : "
  83. + parentKey);
  84. ShardedCounter shard = getMergedShardedCounter(parentKey);
  85. int value;
  86. if (shard == null)
  87. value = ServiceConstants.ZERO;
  88. else
  89. value = shard.getNegativePoint();
  90. return value;
  91. }
  92. @Override
  93. public int getPositivePoint(String parentKey) {
  94. logger.debug("Getting negative point count from sharded counter for parent key : "
  95. + parentKey);
  96. ShardedCounter shard = getMergedShardedCounter(parentKey);
  97. int value;
  98. if (shard == null)
  99. value = ServiceConstants.ZERO;
  100. else
  101. value = shard.getPositivePoint();
  102. return value;
  103. }
  104. @Override
  105. public long getTotalPoint(String parentKey) {
  106. logger.debug("Getting total points from sharded counter for parent key : " + parentKey);
  107. ShardedCounter shard = getMergedShardedCounter(parentKey);
  108. long value;
  109. if (shard == null)
  110. value = ServiceConstants.ZERO;
  111. else
  112. value = shard.getTotalPoint();
  113. return value;
  114. }
  115. @Override
  116. @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  117. public void incrementNegativePoints(String parentKey) {
  118. logger.debug("Incrementing negative point in sharded counter for parent key: "
  119. + parentKey);
  120. if (parentKey == null) {
  121. logger.debug("Parent key value is null : ");
  122. return;
  123. }
  124. Random generator = new Random();
  125. int shardNum = generator.nextInt(DaoConstants.SHARDED_COUNTERS);
  126. List<ShardedCounter> shards = shardedCounterDao.getShardsByParentKeyAndShardNum(
  127. parentKey, shardNum);
  128. ShardedCounter shard = null;
  129. ShardedCounter shardToUpdate = null;
  130. if (shards == null || shards.isEmpty()) {
  131. shardToUpdate = new ShardedCounter(parentKey);
  132. shardToUpdate.setNegativePoint(DaoConstants.ONE);
  133. shardToUpdate.setShardNumber(shardNum);
  134. } else {
  135. shard = shards.get(0);
  136. shardToUpdate = getShardCopy(shard);
  137. shardToUpdate.setNegativePoint(shardToUpdate.getNegativePoint() + DaoConstants.ONE);
  138. }
  139. shardedCounterDao.createOrUpdateShardedCounter(shardToUpdate);
  140. logger.debug("Negative point incremented in sharded counter for parent key : " + parentKey);
  141. }
  142. @Override
  143. @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  144. public void incrementPositivePoints(String parentKey) {
  145. logger.debug("Incrementing positive point in sharded counter for parent key: "
  146. + parentKey);
  147. if (parentKey == null) {
  148. logger.debug("Parent key value is null : ");
  149. return;
  150. }
  151. Random generator = new Random();
  152. int shardNum = generator.nextInt(DaoConstants.SHARDED_COUNTERS);
  153. List<ShardedCounter> shards = shardedCounterDao.getShardsByParentKeyAndShardNum(
  154. parentKey, shardNum);
  155. ShardedCounter shard = null;
  156. ShardedCounter shardToUpdate = null;
  157. if (shards == null || shards.isEmpty()) {
  158. shardToUpdate = new ShardedCounter(parentKey);
  159. shardToUpdate.setPositivePoint(DaoConstants.ONE);
  160. shardToUpdate.setShardNumber(shardNum);
  161. } else {
  162. shard = shards.get(0);
  163. shardToUpdate = getShardCopy(shard);
  164. shardToUpdate.setPositivePoint(shardToUpdate.getPositivePoint() + DaoConstants.ONE);
  165. }
  166. shardedCounterDao.createOrUpdateShardedCounter(shardToUpdate);
  167. logger.debug("Negative point incremented in sharded counter for parent key : " + parentKey);
  168. }
  169. @Override
  170. @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  171. public void updateTotalPoints(String parentKey, long points) {
  172. logger.debug("updating total point in sharded counter for parent key: "
  173. + parentKey + "with points " + points);
  174. if (parentKey == null) {
  175. logger.debug("Parent key value is null : ");
  176. return;
  177. }
  178. // Choose the shard randomly from the available shards.
  179. Random generator = new Random();
  180. int shardNum = generator.nextInt(DaoConstants.SHARDED_COUNTERS);
  181. List<ShardedCounter> shards = shardedCounterDao.getShardsByParentKeyAndShardNum(
  182. parentKey, shardNum);
  183. ShardedCounter shard = null;
  184. ShardedCounter shardToUpdate = null;
  185. if (shards == null || shards.isEmpty()) {
  186. shardToUpdate = new ShardedCounter(parentKey);
  187. shardToUpdate.setTotalPoint(points);
  188. shardToUpdate.setShardNumber(shardNum);
  189. } else {
  190. shard = shards.get(0);
  191. shardToUpdate = getShardCopy(shard);
  192. shardToUpdate.setTotalPoint(shardToUpdate.getTotalPoint() + points);
  193. }
  194. shardedCounterDao.createOrUpdateShardedCounter(shardToUpdate);
  195. logger.debug("Total point updated in sharded counter for parent key : " + parentKey);
  196. }
  197. /**
  198. * @param points
  199. * @param shard
  200. * @return
  201. */
  202. private ShardedCounter getShardCopy(ShardedCounter shard) {
  203. ShardedCounter shardToUpdate;
  204. shardToUpdate = new ShardedCounter(shard.getParentKey());
  205. shardToUpdate.setKey(shard.getKey());
  206. shardToUpdate.setNegativePoint(shard.getNegativePoint());
  207. shardToUpdate.setShardNumber(shard.getShardNumber());
  208. shardToUpdate.setPositivePoint(shard.getPositivePoint());
  209. shardToUpdate.setTotalPoint(shard.getTotalPoint());
  210. return shardToUpdate;
  211. }
  212. /**
  213. * Getter for sharded counter dao.
  214. *
  215. * @return ShardedCounterDao
  216. */
  217. public ShardedCounterDao getShardedCounterDao() {
  218. return shardedCounterDao;
  219. }
  220. /**
  221. * Setter for sharded counter dao.
  222. *
  223. * @param shardedCounterDao ShardedCounterDao
  224. */
  225. public void setShardedCounterDao(ShardedCounterDao shardedCounterDao) {
  226. this.shardedCounterDao = shardedCounterDao;
  227. }
  228. }