PageRenderTime 67ms CodeModel.GetById 18ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 1ms

/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
 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