package com.delect.motiver.server.cache; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import com.delect.motiver.server.dao.helper.WorkoutSearchParams; import com.delect.motiver.server.jdo.UserOpenid; import com.delect.motiver.server.jdo.training.ExerciseName; import com.delect.motiver.server.jdo.training.Routine; import com.delect.motiver.server.jdo.training.Workout; import com.delect.motiver.server.service.MyServiceImpl; import com.google.appengine.api.memcache.Expiration; import com.google.appengine.api.memcache.MemcacheService; import com.google.appengine.api.memcache.MemcacheService.IdentifiableValue; import com.google.appengine.api.memcache.MemcacheServiceFactory; import com.prodeagle.java.counters.Counter; public class TrainingCache { private final static boolean CACHE_ON = true; private final static String PREFIX_WORKOUTS = "tca_ws2"; private final static String PREFIX_WORKOUT = "tca_w"; private final static String PREFIX_ROUTINE = "tca_r"; private final static String PREFIX_EXERCISE_NAME = "tca_en1_"; private final static String PREFIX_EXERCISE_NAMES = "tca_en2a_"; private final static String PREFIX_EXERCISE_NAME_COUNT = "tca_en_c"; private final static int CACHE_EXPIRE_SECONDS = 7 * 24 * 60 * 60; /** * Logger for this class */ private static final Logger logger = Logger.getLogger(TrainingCache.class.getName()); private static final Expiration DEFAULT_EXPIRATION = Expiration.byDeltaSeconds(CACHE_EXPIRE_SECONDS); MemcacheService cache = MemcacheServiceFactory.getMemcacheService(); private static TrainingCache trainingCache; public static TrainingCache getInstance() { if(trainingCache == null) { trainingCache = new TrainingCache(); } return trainingCache; } @SuppressWarnings("unchecked") public Set<Long> getWorkouts(WorkoutSearchParams params) { if(cache == null || !CACHE_ON) { return null; } StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_WORKOUTS); builder.append("_"); params.getCacheKey(builder); Object obj = cache.get(builder.toString()); Set<Long> workouts = null; if(obj instanceof Set) { workouts = (Set<Long>)obj; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Loaded workouts ("+params.uid+", "+params.date+"): "+workouts); } return workouts; } public void setWorkouts(WorkoutSearchParams params, Set<Long> workouts) { if(cache == null || !CACHE_ON) { return; } StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_WORKOUTS); builder.append("_"); params.getCacheKey(builder); cache.put(builder.toString(), workouts, DEFAULT_EXPIRATION); } public Workout getWorkout(Long workoutId) { if(!CACHE_ON) { return null; } //workout StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_WORKOUT); builder.append(workoutId); Object obj = cache.get(builder.toString()); Workout t = null; if(obj != null && obj instanceof Workout) { //prodeagle counter Counter.increment("Cache.Workout"); t = (Workout)obj; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Loaded workout ("+workoutId+"): "+t); } return t; } public void addWorkout(Workout workout) { if(!CACHE_ON) { return; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Saving single workout: "+workout); } MemcacheService cache = MemcacheServiceFactory.getMemcacheService(); //workout StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_WORKOUT); builder.append(workout.getId()); String s = builder.toString(); boolean ok = false; while(!ok) { IdentifiableValue oldValue = cache.getIdentifiable(s); if(oldValue != null) ok = cache.putIfUntouched(s, oldValue, workout, DEFAULT_EXPIRATION); else { cache.put(s, workout, DEFAULT_EXPIRATION); ok = true; } } } public void removeWorkout(Long workoutId) { if(cache == null || !CACHE_ON) { return; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Removing single workout: "+workoutId); } StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_WORKOUT); builder.append(workoutId); cache.delete(builder.toString()); } public void removeRoutine(Long routineId) { if(cache == null || !CACHE_ON) { return; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Removing single routine: "+routineId); } StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_ROUTINE); builder.append(routineId); cache.delete(builder.toString()); } @SuppressWarnings("unchecked") public Map<Long, String> getExerciseNames(String locale) { if(cache == null || !CACHE_ON) { return null; } StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_EXERCISE_NAMES); builder.append(locale); builder.append("_"); Object obj = cache.get(builder.toString()); Map<Long, String> names = null; if(obj instanceof Map) { //prodeagle counter Counter.increment("Cache.ExerciseNames"); names = (Map<Long, String>)obj; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Loaded exercise names: "+((names != null)? names.size() : 0)); } return names; } @SuppressWarnings("unchecked") public void updateExerciseNames(String locale, ExerciseName name) { if(cache == null || !CACHE_ON) { return; } StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_EXERCISE_NAMES); builder.append(locale); builder.append("_"); String s = builder.toString(); //get old value boolean ok = false; while(!ok) { IdentifiableValue oldValue = cache.getIdentifiable(s); if(oldValue != null) { Map<Long, String> names = (Map<Long, String>) oldValue.getValue(); names.put(name.getId(), name.getName()); ok = cache.putIfUntouched(s, oldValue, names, DEFAULT_EXPIRATION); } else ok = true; } } public void setExerciseNames(String locale, Map<Long, String> map) { if(cache == null || !CACHE_ON) { return; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Saving exercise names: "+map.size()); } StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_EXERCISE_NAMES); builder.append(locale); builder.append("_"); String s = builder.toString(); boolean ok = false; while(!ok) { IdentifiableValue oldValue = cache.getIdentifiable(s); if(oldValue != null) ok = cache.putIfUntouched(s, oldValue, map, DEFAULT_EXPIRATION); else { cache.put(s, map, DEFAULT_EXPIRATION); ok = true; } } } public int getExerciseNameCount(UserOpenid user, Long id) { if(cache == null || !CACHE_ON) { return -1; } StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_EXERCISE_NAME_COUNT); builder.append(id); builder.append("_"); builder.append(user.getUid()); Object obj = cache.get(builder.toString()); int c = (obj != null)? (Integer)obj : -1; if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Loaded exercise name count ("+user.getUid()+", "+id+"): "+c); } return c; } public void setExerciseNameCount(UserOpenid user, Long id, int count) { if(cache == null || !CACHE_ON) { return; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Saving exercise name count ("+user.getUid()+", "+id+", "+count+")"); } StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_EXERCISE_NAME_COUNT); builder.append(id); builder.append("_"); builder.append(user.getUid()); cache.put(builder.toString(), count, DEFAULT_EXPIRATION); } public Routine getRoutine(Long routineId) { if(cache == null || !CACHE_ON) { return null; } //routine StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_ROUTINE); builder.append(routineId); Object obj = cache.get(builder.toString()); Routine t = null; if(obj != null && obj instanceof Routine) { //prodeagle counter Counter.increment("Cache.Routine"); t = (Routine)obj; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Loaded single routine ("+routineId+"): "+t); } return t; } public void addRoutine(Routine routine) { if(cache == null || !CACHE_ON) { return; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Saving single routine: "+routine); } //routine StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_ROUTINE); builder.append(routine.getId()); cache.put(builder.toString(), routine, DEFAULT_EXPIRATION); } public ExerciseName getExerciseName(Long key) { if(cache == null || !CACHE_ON) { return null; } //workout StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_EXERCISE_NAME); builder.append(key); Object obj = cache.get(builder.toString()); ExerciseName t = null; if(obj != null && obj instanceof ExerciseName) { //prodeagle counter Counter.increment("Cache.ExerciseName"); t = (ExerciseName)obj; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Loaded exercise name ("+key+"): "+t); } return t; } public void addExerciseName(ExerciseName jdo) { if(cache == null || !CACHE_ON) { return; } if(logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Saving single exercise name: "+jdo); } //exercise name StringBuilder builder = MyServiceImpl.getStringBuilder(); builder.append(PREFIX_EXERCISE_NAME); builder.append(jdo.getId()); String s = builder.toString(); boolean ok = false; while(!ok) { IdentifiableValue oldValue = cache.getIdentifiable(s); if(oldValue != null) ok = cache.putIfUntouched(s, oldValue, jdo, DEFAULT_EXPIRATION); else { cache.put(s, jdo, DEFAULT_EXPIRATION); ok = true; } } //add to "search" cache updateExerciseNames(jdo.getLocale(), jdo); } }