/src/main/java/com/google/ie/business/service/impl/ShardedCounterServiceImpl.java
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 16package com.google.ie.business.service.impl; 17 18import com.google.ie.business.dao.ShardedCounterDao; 19import com.google.ie.business.dao.impl.DaoConstants; 20import com.google.ie.business.domain.ShardedCounter; 21import com.google.ie.business.service.IdeaService; 22import com.google.ie.business.service.ServiceConstants; 23import com.google.ie.business.service.ShardedCounterService; 24import com.google.ie.common.cache.CacheConstants; 25import com.google.ie.common.cache.CacheHelper; 26 27import org.apache.log4j.Logger; 28import org.springframework.beans.factory.annotation.Autowired; 29import org.springframework.stereotype.Service; 30import org.springframework.transaction.annotation.Propagation; 31import org.springframework.transaction.annotation.Transactional; 32 33import java.util.List; 34import java.util.Random; 35 36/** 37 * A service implementation of the {@link ShardedCounterService}. 38 * 39 * @author gmaurya 40 * 41 */ 42@Service 43public class ShardedCounterServiceImpl implements ShardedCounterService { 44 45 private static Logger logger = Logger.getLogger(ShardedCounterServiceImpl.class); 46 47 @Autowired 48 private ShardedCounterDao shardedCounterDao; 49 50 @Autowired 51 private IdeaService ideaService; 52 53 public IdeaService getIdeaService() { 54 return ideaService; 55 } 56 57 public void setIdeaService(IdeaService ideaService) { 58 this.ideaService = ideaService; 59 } 60 61 private static final int CACHEDELAY = 120; 62 63 @Override 64 public ShardedCounter getMergedShardedCounter(String parentKey) { 65 logger.debug("Getting Merged sharded counter for parent key : " + parentKey); 66 if (parentKey == null) 67 return null; 68 69 Object obj = CacheHelper.getObject(CacheConstants.IDEA_SHARD_NAMESPACE, parentKey); 70 ShardedCounter shardedCounter = null; 71 72 if (obj != null && obj instanceof ShardedCounter) { 73 shardedCounter = (ShardedCounter) obj; 74 } 75 76 // Retrieve merged sharded counter from datastore 77 if (shardedCounter == null) { 78 79 shardedCounter = new ShardedCounter(parentKey); 80 List<ShardedCounter> shards = shardedCounterDao.getShardsByParentKey(parentKey); 81 if (shards != null && !shards.isEmpty()) { 82 for (ShardedCounter shard : shards) { 83 shardedCounter.setTotalPoint(shard.getTotalPoint() 84 + shardedCounter.getTotalPoint()); 85 shardedCounter.setNegativePoint(shard.getNegativePoint() 86 + shardedCounter.getNegativePoint()); 87 shardedCounter.setPositivePoint(shard.getPositivePoint() 88 + shardedCounter.getPositivePoint()); 89 } 90 } 91 92 CacheHelper.putObject(CacheConstants.IDEA_SHARD_NAMESPACE, parentKey, shardedCounter, 93 CACHEDELAY); 94 95 } 96 return shardedCounter; 97 } 98 99 @Override 100 public int getNegativePoint(String parentKey) { 101 logger.debug("Getting negative point count from sharded counter for parent key : " 102 + parentKey); 103 ShardedCounter shard = getMergedShardedCounter(parentKey); 104 int value; 105 if (shard == null) 106 value = ServiceConstants.ZERO; 107 else 108 value = shard.getNegativePoint(); 109 110 return value; 111 } 112 113 @Override 114 public int getPositivePoint(String parentKey) { 115 logger.debug("Getting negative point count from sharded counter for parent key : " 116 + parentKey); 117 ShardedCounter shard = getMergedShardedCounter(parentKey); 118 int value; 119 if (shard == null) 120 value = ServiceConstants.ZERO; 121 else 122 value = shard.getPositivePoint(); 123 124 return value; 125 } 126 127 @Override 128 public long getTotalPoint(String parentKey) { 129 logger.debug("Getting total points from sharded counter for parent key : " + parentKey); 130 ShardedCounter shard = getMergedShardedCounter(parentKey); 131 long value; 132 if (shard == null) 133 value = ServiceConstants.ZERO; 134 else 135 value = shard.getTotalPoint(); 136 137 return value; 138 } 139 140 @Override 141 @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 142 public void incrementNegativePoints(String parentKey) { 143 144 logger.debug("Incrementing negative point in sharded counter for parent key: " 145 + parentKey); 146 if (parentKey == null) { 147 logger.debug("Parent key value is null : "); 148 return; 149 } 150 Random generator = new Random(); 151 int shardNum = generator.nextInt(DaoConstants.SHARDED_COUNTERS); 152 List<ShardedCounter> shards = shardedCounterDao.getShardsByParentKeyAndShardNum( 153 parentKey, shardNum); 154 ShardedCounter shard = null; 155 ShardedCounter shardToUpdate = null; 156 if (shards == null || shards.isEmpty()) { 157 shardToUpdate = new ShardedCounter(parentKey); 158 shardToUpdate.setNegativePoint(DaoConstants.ONE); 159 shardToUpdate.setShardNumber(shardNum); 160 } else { 161 shard = shards.get(0); 162 shardToUpdate = getShardCopy(shard); 163 shardToUpdate.setNegativePoint(shardToUpdate.getNegativePoint() + DaoConstants.ONE); 164 } 165 shardedCounterDao.createOrUpdateShardedCounter(shardToUpdate); 166 logger.debug("Negative point incremented in sharded counter for parent key : " + parentKey); 167 168 } 169 170 @Override 171 @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 172 public void incrementPositivePoints(String parentKey) { 173 logger.debug("Incrementing positive point in sharded counter for parent key: " 174 + parentKey); 175 if (parentKey == null) { 176 logger.debug("Parent key value is null : "); 177 return; 178 } 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.setPositivePoint(DaoConstants.ONE); 188 shardToUpdate.setShardNumber(shardNum); 189 } else { 190 shard = shards.get(0); 191 shardToUpdate = getShardCopy(shard); 192 shardToUpdate.setPositivePoint(shardToUpdate.getPositivePoint() + DaoConstants.ONE); 193 } 194 shardedCounterDao.createOrUpdateShardedCounter(shardToUpdate); 195 logger.debug("Negative point incremented in sharded counter for parent key : " + parentKey); 196 197 } 198 199 @Override 200 @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 201 public void updateTotalPoints(String parentKey, long points) { 202 logger.debug("updating total point in sharded counter for parent key: " 203 + parentKey + "with points " + points); 204 if (parentKey == null) { 205 logger.debug("Parent key value is null : "); 206 return; 207 } 208 // Choose the shard randomly from the available shards. 209 Random generator = new Random(); 210 int shardNum = generator.nextInt(DaoConstants.SHARDED_COUNTERS); 211 List<ShardedCounter> shards = shardedCounterDao.getShardsByParentKeyAndShardNum( 212 parentKey, shardNum); 213 ShardedCounter shard = null; 214 ShardedCounter shardToUpdate = null; 215 if (shards == null || shards.isEmpty()) { 216 shardToUpdate = new ShardedCounter(parentKey); 217 shardToUpdate.setTotalPoint(points); 218 shardToUpdate.setShardNumber(shardNum); 219 220 } else { 221 shard = shards.get(0); 222 shardToUpdate = getShardCopy(shard); 223 shardToUpdate.setTotalPoint(shardToUpdate.getTotalPoint() + points); 224 } 225 226 shardedCounterDao.createOrUpdateShardedCounter(shardToUpdate); 227 logger.debug("Total point updated in sharded counter for parent key : " + parentKey); 228 229 } 230 231 /** 232 * @param points 233 * @param shard 234 * @return 235 */ 236 private ShardedCounter getShardCopy(ShardedCounter shard) { 237 ShardedCounter shardToUpdate; 238 shardToUpdate = new ShardedCounter(shard.getParentKey()); 239 shardToUpdate.setKey(shard.getKey()); 240 shardToUpdate.setNegativePoint(shard.getNegativePoint()); 241 shardToUpdate.setShardNumber(shard.getShardNumber()); 242 shardToUpdate.setPositivePoint(shard.getPositivePoint()); 243 shardToUpdate.setTotalPoint(shard.getTotalPoint()); 244 245 return shardToUpdate; 246 } 247 248 /** 249 * Getter for sharded counter dao. 250 * 251 * @return ShardedCounterDao 252 */ 253 public ShardedCounterDao getShardedCounterDao() { 254 return shardedCounterDao; 255 } 256 257 /** 258 * Setter for sharded counter dao. 259 * 260 * @param shardedCounterDao ShardedCounterDao 261 */ 262 public void setShardedCounterDao(ShardedCounterDao shardedCounterDao) { 263 this.shardedCounterDao = shardedCounterDao; 264 } 265 266} 267