All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.objectify.util.Monotonic Maven / Gradle / Ivy

Go to download

*** THIS VERSION UPLOADED FOR USE WITH CEDAR-COMMON, TO AVOID DEPENDENCIES ON GOOGLE CODE-BASED MAVEN REPOSITORIES. *** The simplest convenient interface to the Google App Engine datastore

The newest version!
/*
 * $Id$
 */

package com.googlecode.objectify.util;

import java.lang.reflect.Field;

import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.impl.TypeUtils;

/**
 * 

Provides a method for generating contiguous, monotonically increasing values.

* *

The datastore will automatically generate unique ids for your entities if you * use a Long @Id value and create an object with a null id. Unfortunately this id * is not guaranteed to increase monotonically, so you cannot use it for time-ordering. * You also cannot use datestamps for time-ordering because clock skew among GAE instances * is not guaranteed to fall within any particular bound; they could, in theory, be * minutes off.

* *

This class uses the memcache service to efficiently generate a monotonically * increasing number which *can* be used for time-ordering. This can be used, for example, * to create revision ids. It can also be used to generate the change numbers needed to keep * a slave database in sync.

* *

The data must be stored on a field of an entity. The field MUST be indexed.

* * @author Jeff Schnitzer */ public class Monotonic { /** * Get the next unique, monotonically increasing, contiguous value for a field * on an entity class. The field MUST be indexed or this method will always * return 1. */ public static long next(Objectify ofy, Class entityClass, String fieldName) { String cacheKey = "monotonic-" + entityClass.getName() + "." + fieldName; MemcacheService memcache = MemcacheServiceFactory.getMemcacheService(); Long nextValue = memcache.increment(cacheKey, 1); if (nextValue == null) { long lastValue = getMax(ofy, entityClass, fieldName); nextValue = memcache.increment(cacheKey, 1, lastValue); } if (nextValue == null) throw new IllegalStateException("Memcache service currently not operating"); else return nextValue; } /** * Query for the max value of a field for all entities, or return 1 if there are no * entities. The field must be a numeric type and it MUST be indexed. */ private static long getMax(Objectify ofy, Class entityClass, String fieldName) { Object thing = ofy.query(entityClass).order("-" + fieldName).get(); if (thing != null) { try { Field f = TypeUtils.getDeclaredField(entityClass, fieldName); f.setAccessible(true); Number n = (Number)f.get(thing); if (n == null) return 0; else return n.longValue(); } catch (Exception e) { throw new IllegalStateException(e); } } else return 0; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy