Package com.spaceprogram.simplejpa

Source Code of com.spaceprogram.simplejpa.EntityManagerSimpleJPA

package com.spaceprogram.simplejpa;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityTransaction;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import com.amazonaws.AmazonClientException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.simpledb.AmazonSimpleDB;
import com.amazonaws.services.simpledb.model.Attribute;
import com.amazonaws.services.simpledb.model.DeleteAttributesRequest;
import com.amazonaws.services.simpledb.model.GetAttributesRequest;
import com.amazonaws.services.simpledb.model.GetAttributesResult;
import com.amazonaws.services.simpledb.model.Item;
import com.amazonaws.services.simpledb.model.PutAttributesRequest;
import com.amazonaws.services.simpledb.model.ReplaceableAttribute;
import com.amazonaws.services.simpledb.model.SelectResult;
import com.spaceprogram.simplejpa.AnnotationManager.ClassMethodEntry;
import com.spaceprogram.simplejpa.cache.Cache;
import com.spaceprogram.simplejpa.operations.Delete;
import com.spaceprogram.simplejpa.operations.Find;
import com.spaceprogram.simplejpa.operations.Save;
import com.spaceprogram.simplejpa.query.QueryImpl;
import com.spaceprogram.simplejpa.stats.OpStats;
import com.spaceprogram.simplejpa.util.AmazonSimpleDBUtil;
import com.spaceprogram.simplejpa.util.ConcurrentRetriever;

import net.sf.cglib.proxy.Factory;

import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.lang.StringUtils;

/**
* User: treeder Date: Feb 8, 2008 Time: 12:59:38 PM
*
* Additional Contributions - Eric Molitor eric@molitor.org - Eric Wei e.pwei84@gmail.com
*/
public class EntityManagerSimpleJPA implements SimpleEntityManager, DatabaseManager {

    private static Logger logger = Logger.getLogger(EntityManagerSimpleJPA.class.getName());
    private boolean closed = false;
    public EntityManagerFactoryImpl factory;
    private boolean sessionless;
    private boolean consistentRead = true;
    /**
     * cache is used to store objects retrieved in this EntityManager session
     */
    private Map sessionCache;
    /**
     * used for converting numbers to strings
     */
    public static final BigDecimal OFFSET_VALUE = new BigDecimal(Long.MIN_VALUE).negate();
    private OpStats lastOpStats = new OpStats(); // todo: thread local this
    private OpStats totalOpStats = new OpStats();

    EntityManagerSimpleJPA(EntityManagerFactoryImpl factory, boolean sessionless) {
        this.factory = factory;
        this.sessionless = sessionless;
        if (!sessionless) {
            sessionCache = new ConcurrentHashMap();
        }
        this.consistentRead = factory.isConsistentRead();
    }

    public void persist(Object o) {
        resetLastOpStats();
        try {
            new Save(this, o).call();
        } catch (AmazonClientException e) {
            throw new PersistenceException("Could not get SimpleDb Domain", e);
        } catch (Exception e) {
            throw new PersistenceException(e);
        }
    }

    public Future persistAsync(Object o) {
        Future future = getExecutor().submit(new Save(this, o));
        return future;
    }

    public Future removeAsync(Object o) {
        Future future = getExecutor().submit(new Delete(this, o));
        return future;
    }

    public <T> Future<T> findAsync(Class<T> tClass, Object o) {
        Future<T> future = getExecutor().submit(new Find(this, tClass, o));
        return future;
    }

    private void resetLastOpStats() {
        lastOpStats = new OpStats();
    }

    public <T> T merge(T t) {
        // todo: should probably behave a bit different
        persist(t);
        return t;
    }

    public String s3ObjectId(String id, Method getter) {
        return id + "-" + NamingHelper.attributeName(getter);
    }

    public static String padOrConvertIfRequired(Object ob) {
        if (ob instanceof Integer || ob instanceof Long) {
            // then pad
            return AmazonSimpleDBUtil.encodeRealNumberRange(new BigDecimal(ob.toString()), AmazonSimpleDBUtil.LONG_DIGITS, OFFSET_VALUE);
        } else if ((ob instanceof Double && !((Double) ob).isInfinite() && !((Double) ob).isNaN())
                || (ob instanceof Float && !((Float) ob).isInfinite() && !((Float) ob).isNaN())) {
            // then pad
            return AmazonSimpleDBUtil.encodeRealNumberRange(new BigDecimal(ob.toString()), AmazonSimpleDBUtil.LONG_DIGITS, AmazonSimpleDBUtil.LONG_DIGITS,
                    OFFSET_VALUE);
        } else if (ob instanceof BigDecimal) {
            // then pad
            return AmazonSimpleDBUtil.encodeRealNumberRange((BigDecimal) ob, AmazonSimpleDBUtil.LONG_DIGITS, AmazonSimpleDBUtil.LONG_DIGITS, OFFSET_VALUE);
        } else if (ob instanceof Date) {
            Date d = (Date) ob;
            return AmazonSimpleDBUtil.encodeDate(d);
        } else if (ob instanceof byte[]) {
            return AmazonSimpleDBUtil.encodeByteArray((byte[]) ob);
        }
        return ob.toString();
    }

    /**
     * Get's the identifier for the object based on @Id
     *
     * @param o
     * @return
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public String getId(Object o) {
        AnnotationInfo ai = factory.getAnnotationManager().getAnnotationInfo(o);
        if (ai == null)
            return null; // todo: should it throw?
        String id = null;
        try {
            id = (String) ai.getIdMethod().invoke(o);
        } catch (IllegalAccessException e) {
            throw new PersistenceException(e);
        } catch (InvocationTargetException e) {
            throw new PersistenceException(e);
        }
        return id;
    }

    public String getDomainName(Class<? extends Object> aClass) {
        return factory.getDomainName(aClass);
    }

    public String getOrCreateDomain(Class c) {
        return factory.getOrCreateDomain(c);
    }

    public void checkEntity(Object o) {
// String className = o.getClass().getName();
// ensureClassIsEntity(className); THIS IS DONE IN getAnnotationInfo now
        // now if it the reflection data hasn't been cached, do it now
        AnnotationInfo ai = factory.getAnnotationManager().getAnnotationInfo(o);
        String domainName = getDomainName(o.getClass());
        factory.setupDbDomain(domainName);
    }

    public Class ensureClassIsEntity(String className) {
// System.out.println("className=" + className);
        className = factory.getAnnotationManager().stripEnhancerClass(className);
        String fullClassName = factory.getEntityMap().get(className);
        if (fullClassName == null) {
// throw new PersistenceException("Class not marked as an Entity: " + className);
            fullClassName = className;
        }
// System.out.println("fullclassName=" + fullClassName);
        Class tClass = factory.getAnnotationManager().getClass(fullClassName, null);
        AnnotationInfo ai = factory.getAnnotationManager().getAnnotationInfo(tClass); // sets up metadata if not already done
        return tClass;
    }

    public AmazonSimpleDB getSimpleDb() {
        return factory.getSimpleDb();
    }

    /**
     * Deletes an object from SimpleDB.
     *
     * @param o
     */
    public void remove(Object o) {
        if (o == null)
            return;
        try {
            Delete d = new Delete(this, o);
            d.call();
        } catch (Exception e) {
            throw new PersistenceException(e);
        }
    }

    /**
     * Finds an object by id.
     *
     * @param tClass
     * @param id
     * @return
     */
    public <T> T find(Class<T> tClass, Object id) {
        if (!sessionless && closed)
            throw new PersistenceException("EntityManager already closed.");
        if (id == null)
            throw new IllegalArgumentException("Id value must not be null.");
        try {
            T ob = cacheGet(tClass, id);
            if (ob != null) {
                if (logger.isLoggable(Level.FINEST)) {
                    logger.finest("found in cache: " + ob);
                }
                return ob;
            }
            return findInDb(tClass, id);
        } catch (AmazonClientException e) {
            throw new PersistenceException(e);
        }
    }

    private <T> T findInDb(Class<T> tClass, Object id) throws AmazonClientException {
        String domainName = getDomainName(tClass);
        if (domainName == null)
            return null;
        Item iraw = DomainHelper.findItemById(factory.getSimpleDb(), domainName, id.toString(), consistentRead);
// logger.fine("got back item=" + item);
        if (iraw == null)
            return null;
        SdbItem item = new SdbItemImpl2(iraw);
        return getItemAttributesBuildAndCache(tClass, id, item);

    }

    /**
     * If you already have reference to an Item, can use this build the object and cache it.
     * @param tClass
     * @param id
     * @param item
     * @return
     * @throws AmazonClientException
     */
    public <T> T getItemAttributesBuildAndCache(Class<T> tClass, Object id, SdbItem item) throws AmazonClientException {
        // todo: update stats for this get
        List<Attribute> atts = item.getAttributes();
        if (atts == null || atts.size() == 0)
            return null;
        return buildObject(tClass, id, atts);
    }

    public void renameField(Class tClass, String oldAttributeName, String newAttributeName) {
        // get list of all items in the domain
        try {
            String domainName = getDomainName(tClass);
            SelectResult result;
            List<Item> items;
            int i = 0;
            String nextToken = null;
            while (i == 0 || nextToken != null) {
                result = executeQueryForRename(oldAttributeName, newAttributeName, domainName, nextToken);
                items = result.getItems();
                putAndDelete(domainName, oldAttributeName, newAttributeName, items);
                nextToken = result.getNextToken();
                i++;
                if (i % 100 == 0) {
                    System.out.println("Renamed " + i + " fields so far...");
                }
            }
        } catch (AmazonClientException e) {
            e.printStackTrace();
        }
    }

    public void renameSubclass(String oldClassName, Class newClass) {
        logger.info("Renaming DTYPE for " + oldClassName + " to " + newClass.getSimpleName());
        try {
            String newClassName = newClass.getSimpleName();
            String domainName = factory.getDomainName(newClass);
            SelectResult result;
            List<Item> items;
            int i = 0;
            String nextToken = null;
            while (i == 0 || nextToken != null) {
                result = executeQueryForRenameSubclass(oldClassName, newClass, domainName, nextToken);
                items = result.getItems();
                putNewValue(domainName, items, EntityManagerFactoryImpl.DTYPE, newClassName);
                nextToken = result.getNextToken();
                i++;
                if (i % 100 == 0) {
                    System.out.println("Renamed " + i + " subclassed objects so far...");
                }
            }
        } catch (AmazonClientException e) {
            e.printStackTrace();
        }
    }

    private void putNewValue(String domainName, List<Item> items, String dtype, String newClassName) throws AmazonClientException {
        AmazonSimpleDB db = factory.getSimpleDb();
        for (Item item : items) {
            List<ReplaceableAttribute> atts = new ArrayList<ReplaceableAttribute>();

            atts.add(new ReplaceableAttribute(dtype, newClassName, true));
            db.putAttributes(new PutAttributesRequest(domainName, item.getName(), atts));
        }
    }

    private SelectResult executeQueryForRenameSubclass(String oldClassName, Class newClass, String domainName, String nextToken) throws AmazonClientException {
        SelectResult result = DomainHelper.selectItems(factory.getSimpleDb(), domainName, "'DTYPE' = '" + oldClassName + "'", nextToken, consistentRead);
        return result;
    }

    private SelectResult executeQueryForRename(String oldAttributeName, String newAttributeName, String domainName, String nextToken)
            throws AmazonClientException {
        SelectResult result = DomainHelper.selectItems(factory.getSimpleDb(), domainName, "['" + oldAttributeName + "' starts-with ''] intersection not ['"
                + newAttributeName + "' starts-with ''] ", nextToken, consistentRead);
        return result;
    }

    private void putAndDelete(String domainName, String oldAttributeName, String newAttributeName, List<Item> items) throws AmazonClientException {
        AmazonSimpleDB db = factory.getSimpleDb();
        for (Item item : items) {
            GetAttributesResult getOldResults = db.getAttributes(new GetAttributesRequest().withDomainName(domainName).withConsistentRead(true).withItemName(
                    item.getName()).withAttributeNames(oldAttributeName));

            List<Attribute> oldAtts = getOldResults.getAttributes();
            if (oldAtts.size() > 0) {
                Attribute oldAtt = oldAtts.get(0);
                List<ReplaceableAttribute> atts = new ArrayList<ReplaceableAttribute>();
                atts.add(new ReplaceableAttribute(newAttributeName, oldAtt.getValue(), true));

                db.putAttributes(new PutAttributesRequest().withDomainName(domainName).withItemName(item.getName()).withAttributes(atts));

                db.deleteAttributes(new DeleteAttributesRequest().withDomainName(domainName).withItemName(item.getName()).withAttributes(oldAtts));
            }
        }
    }

    /**
     * This method puts together an object from the SimpleDB data.
     *
     * @param tClass
     * @param id
     * @param atts
     * @return
     */
    public <T> T buildObject(Class<T> tClass, Object id, List<Attribute> atts) {
        return ObjectBuilder.buildObject(this, tClass, id, atts);
    }

    public <T> T cacheGet(Class<T> aClass, Object id) {
        String key = cacheKey(aClass, id);
        logger.finest("getting item from cache with cachekey=" + key);
        T o = sessionCache != null ? (T) sessionCache.get(key) : null;
        if (o == null) {
            Cache c = getFactory().getCache(aClass);
            if (c != null) {
                o = (T) c.getObj(id);
                if (o != null) {
                    logger.finest("Got item from second level cache!");
                    replaceEntityManager(o, this);
                }
            }
        }
        logger.finest("got item from cache=" + o);
        return o;
    }

    public void cachePut(Object id, Object newInstance) {
        String key = cacheKey(newInstance.getClass(), id);
        logger.finest("putting item in cache with cachekey=" + key + " - " + newInstance);
        if (sessionCache != null)
            sessionCache.put(key, newInstance);
        Cache c = getFactory().getCache(newInstance.getClass());
        if (c != null) {
            c.put(id, newInstance);
        }
    }

    public void cachePut(Object o) {
        String id = getId(o);
        cachePut(id, o);
    }

    public Object cacheRemove(Class aClass, String id) {
        String key = cacheKey(aClass, id);
        logger.finest("removing item from cache with cachekey=" + key);
        Object o = sessionCache != null ? sessionCache.remove(key) : null;
        Cache c = getFactory().getCache(aClass);
        if (c != null) {
            Object o2 = c.remove(id);
            if (o == null)
                o = o2;
        }
        logger.finest("removed object from cache=" + o);
        return o;
    }

    public String cacheKey(Class tClass, Object id) {
        return AnnotationManager.stripEnhancerClass(tClass).getName() + "_" + id;
    }

    public Method getSetterFromGetter(Class tClass, Method getter, Class retType) throws NoSuchMethodException {
        return tClass.getMethod(getSetterNameFromGetter(getter), retType);
    }

    String getSetterNameFromGetter(Method getter) {
        return NamingHelper.setterName(NamingHelper.attributeName(getter));
    }

    /**
     * Sets the value on an object field after applying any necessary conversions from SimpleDB strings.
     *
     * @param tClass
     * @param newInstance
     * @param getter
     * @param val
     */
    public <T> void setFieldValue(Class tClass, T newInstance, Method getter, String val) {
        try {
            // need param type
            String attName = NamingHelper.attributeName(getter);
            Class retType = getter.getReturnType();
// logger.fine("getter in setFieldValue = " + attName + " - valAsString=" + valAsString + " rettype=" + retType);
            Method setMethod = tClass.getMethod("set" + StringUtils.capitalize(attName), retType);
            Object newField = null;
            if (Integer.class.isAssignableFrom(retType) || retType == int.class) {
// logger.fine("setting int val " + val + " on field " + attName);
                val = AmazonSimpleDBUtil.decodeRealNumberRange(val, EntityManagerSimpleJPA.OFFSET_VALUE).toString();
                if (retType == int.class)
                    retType = Integer.class;
            } else if (Long.class.isAssignableFrom(retType) || retType == long.class) {
                val = AmazonSimpleDBUtil.decodeRealNumberRange(val, EntityManagerSimpleJPA.OFFSET_VALUE).toString();
                if (retType == long.class)
                    retType = Long.class;
            } else if (Float.class.isAssignableFrom(retType) || retType == float.class) {
                // Ignore NaN and Infinity
                if (!val.matches(".*Infinity|NaN")) {
                    val = AmazonSimpleDBUtil.decodeRealNumberRange(val, AmazonSimpleDBUtil.LONG_DIGITS, EntityManagerSimpleJPA.OFFSET_VALUE).toString();
                }
                if (retType == float.class)
                    retType = Float.class;
            } else if (Double.class.isAssignableFrom(retType) || retType == double.class) {
                // Ignore NaN and Infinity
                if (!val.matches(".*Infinity|NaN")) {
                    val = AmazonSimpleDBUtil.decodeRealNumberRange(val, AmazonSimpleDBUtil.LONG_DIGITS, EntityManagerSimpleJPA.OFFSET_VALUE).toString();
                }
                if (retType == double.class)
                    retType = Double.class;
            } else if (BigDecimal.class.isAssignableFrom(retType)) {
                val = AmazonSimpleDBUtil.decodeRealNumberRange(val, AmazonSimpleDBUtil.LONG_DIGITS, EntityManagerSimpleJPA.OFFSET_VALUE).toString();
            } else if (byte[].class.isAssignableFrom(retType)) {
                newField = AmazonSimpleDBUtil.decodeByteArray(val);
            } else if (Date.class.isAssignableFrom(retType)) {
                newField = AmazonSimpleDBUtil.decodeDate(val);
            }
            // If newField has not been created yet then we create it from val.
            if (newField == null) {
                // We build a new field object here because we may get an argument mismatch otherwise, eg: BigDecimal for an Integer field.
                // todo: getConstructor throws a NoSuchMethodException here, should ensure that these are second class object fields
                Constructor forNewField = retType.getConstructor(val.getClass());
                if (forNewField == null) {
                    throw new PersistenceException("No constructor for field type: " + retType + " that can take a " + val.getClass());
                }
                newField = forNewField.newInstance(val);
            }
            setMethod.invoke(newInstance, newField);
        } catch (Exception e) {
            throw new PersistenceException("Failed setting field of getter: " + getter.getName() + ", using value: " + val, e);
        }
    }

    public <T> T getReference(Class<T> tClass, Object o) {
        throw new NotImplementedException("TODO");
    }

    public void flush() {
        // we're always flushed in the current version so this doesn't have to do anything
// throw new NotImplementedException("TODO");
    }

    public void setFlushMode(FlushModeType flushModeType) {
        throw new NotImplementedException("TODO");
    }

    public FlushModeType getFlushMode() {
        throw new NotImplementedException("TODO");
    }

    public void lock(Object o, LockModeType lockModeType) {
        throw new NotImplementedException("TODO");
    }

    public void refresh(Object o) {
        throw new NotImplementedException("TODO");
    }

    public void clear() {
        checkClosed();
        // this is really only useful with transactions
        if (sessionCache != null) {
            sessionCache = new ConcurrentHashMap();
        }
    }

    private void checkClosed() {
        if (!isOpen()) {
            throw new IllegalStateException("EntityManager has been closed.");
        }
    }

    public boolean contains(Object o) {
        checkClosed();
        Object ob = cacheGet(o.getClass(), getId(o));
        return ob != null;
    }

    public Query createQuery(String s) {
        return new QueryImpl(this, s);
    }

    public Query createNamedQuery(String s) {
        throw new NotImplementedException("TODO");
    }

    public Query createNativeQuery(String s) {
        throw new NotImplementedException("TODO");
    }

    public Query createNativeQuery(String s, Class aClass) {
        throw new NotImplementedException("TODO");
    }

    public Query createNativeQuery(String s, String s1) {
        throw new NotImplementedException("TODO");
    }

    public void joinTransaction() {
        throw new NotImplementedException("TODO");
    }

    public Object getDelegate() {
        throw new NotImplementedException("TODO");
    }

    /**
     * Clears cache and marks as closed.
     */
    public void close() {
        closed = true;
        sessionCache = null;
    }

    public boolean isOpen() {
        return sessionless || !closed;
    }

    public EntityTransaction getTransaction() {
        return new EntityTransactionImpl();
    }

    public ExecutorService getExecutor() {
        return factory.getExecutor();
    }

    public Object getObjectFromS3(String idOnS3) throws AmazonClientException, IOException, ClassNotFoundException {
        long start = System.currentTimeMillis();
        AmazonS3 s3 = factory.getS3Service();
        S3Object s3o = s3.getObject(factory.getS3BucketName(), idOnS3);
        logger.fine("got s3object=" + s3o);
        Object ret = null;
        try {
            ObjectInputStream reader = new ObjectInputStream(new BufferedInputStream((s3o.getObjectContent())));
            ret = reader.readObject();
        } finally {
            s3o.getObjectContent().close();
        }

        statsS3Get(System.currentTimeMillis() - start);
        return ret;
    }

    public void incrementQueryCount() {
        totalOpStats.queries.incrementAndGet();
        factory.getGlobalStats().queries.incrementAndGet();

    }

    /**
     * @return the number of actual queries sent to amazon.
     */
    public int getQueryCount() {
        return totalOpStats.queries.get();
    }

    /**
     * This is mainly for debugging purposes. Will print to system out all of the items in the domain represented by the class parameter.
     *
     * @param c
     * @throws AmazonClientException
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public void listAllObjectsRaw(Class c) throws AmazonClientException, ExecutionException, InterruptedException {

        String domainName = factory.getDomainName(c);
        List<Item> items = DomainHelper.listAllItems(factory.getSimpleDb(), domainName, consistentRead);

        List<ItemAndAttributes> ia = ConcurrentRetriever.getAttributesFromSdb(toSdbItem(items), getExecutor(), this);
        for (ItemAndAttributes itemAndAttributes : ia) {
            System.out.println("item=" + itemAndAttributes.getItem().getIdentifier());
            List<Attribute> atts = itemAndAttributes.getAtts();
            for (Attribute att : atts) {
                System.out.println("\t=" + att.getName() + "=" + att.getValue());
            }
        }
    }

    private List<SdbItem> toSdbItem(List<Item> items) {
        List<SdbItem> ret = new ArrayList<SdbItem>();
        for (Item item : items) {
            ret.add(new SdbItemImpl2(item));
        }
        return ret;
    }

    public void invokeEntityListener(Object o, Class event) {
// System.out.println("invoking entity listeners on " + o + " for " + event);
        Map<Class, List<ClassMethodEntry>> listeners = getAnnotationManager().getAnnotationInfo(o).getEntityListeners();
        if (listeners != null && listeners.containsKey(event)) {
// System.out.println("founder listeners: " + listeners);
            List<ClassMethodEntry> listenerList = listeners.get(event);
            if (listenerList != null) {
                for (ClassMethodEntry listener : listenerList) {
                    try {
                        listener.invoke(o);
                    } catch (Exception e) {
                        throw new PersistenceException("Error invoking entity listener", e);
                    }
                }
            }
        }
    }

    public AnnotationManager getAnnotationManager() {
        return factory.getAnnotationManager();
    }

    public EntityManagerFactoryImpl getFactory() {
        return factory;
    }

    public OpStats getLastOpStats() {
        return lastOpStats;
    }

    public static <T> void replaceEntityManager(T newInstance, EntityManagerSimpleJPA em) {
        if (newInstance instanceof Factory) {
            Factory factory = (Factory) newInstance;
            LazyInterceptor interceptor = (LazyInterceptor) factory.getCallback(0);
            interceptor.setEntityManager(em);
        }
    }

    public void statsS3Get(long duration) {
        getLastOpStats().s3Get(duration);
        totalOpStats.s3Get(duration);
        factory.getGlobalStats().s3Get(duration);
    }

    public void statsS3Put(long duration) {
        getLastOpStats().s3Put(duration);
        totalOpStats.s3Put(duration);
        factory.getGlobalStats().s3Put(duration);
    }

    public void statsAttsPut(int numAtts, long duration2) {
        getLastOpStats().attsPut(numAtts, duration2);
        totalOpStats.attsPut(numAtts, duration2);
        factory.getGlobalStats().attsPut(numAtts, duration2);
    }

    public void statsAttsDeleted(int numAtts, long duration2) {
        getLastOpStats().attsDeleted(numAtts, duration2);
        totalOpStats.attsDeleted(numAtts, duration2);
        factory.getGlobalStats().attsDeleted(numAtts, duration2);
    }

    public OpStats getTotalOpStats() {
        return totalOpStats;
    }

    public OpStats getGlobalOpStats() {
        return factory.getGlobalStats();
    }

    public void statsGets(int numItems, long duration2) {
        getLastOpStats().got(numItems, duration2);
        totalOpStats.got(numItems, duration2);
        factory.getGlobalStats().got(numItems, duration2);
    }

    public String getS3BucketName() {
        return factory.getS3BucketName();
    }

    public AmazonS3 getS3Service() {
        return factory.getS3Service();
    }

    public void setConsistentRead(boolean consistentRead) {
        this.consistentRead = consistentRead;
    }

    public boolean isConsistentRead() {
        return consistentRead;
    }
}
TOP

Related Classes of com.spaceprogram.simplejpa.EntityManagerSimpleJPA

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.