Package gap.data

Source Code of gap.data.Store$C

/*
* Gap Data
* Copyright (C) 2009 John Pritchard
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package gap.data;

import gap.service.Logon;
import gap.util.Page;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheFactory;
import javax.cache.CacheManager;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;

import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;

import javax.servlet.ServletContext;

import java.util.Iterator;

/**
* Memcache - Datastore for Entities and Classes
*/
public final class Store
    extends java.lang.Object
{
    /**
     * Namespace
     */
    protected final static class N
        extends java.lang.Object
    {
        private final static ThreadLocal<String> NTL = new ThreadLocal<String>();

        protected static void Enter(String ns){

            if (null == ns){

                if (null != NTL.get()){

                    NTL.set(null);
                }  
            }
            else if (null == NTL.get()){

                NTL.set(ns);
            }
            /*
             * Valid reentry is possible in some error handling schemes
             */
        }
        protected static void Exit(){
            NTL.remove();
        }
        public static String Get(){
            return NTL.get();
        }
    }
    /**
     * Datastore
     */
    protected final static class P
        extends java.lang.Object
    {
        private final static ThreadLocal<DatastoreService> PTL = new ThreadLocal<DatastoreService>();


        protected static void Enter(String ns){
            DatastoreService ds = PTL.get();
            if (null == ds){
                ds = DatastoreServiceFactory.getDatastoreService();
                PTL.set(ds);
            }
            /*
             * Valid reentry is possible in some error handling schemes
             */
        }
        protected static void Exit(){
            PTL.remove();
        }
        protected static DatastoreService Get(){
            return PTL.get();
        }
        protected static Entity Get(Key key){
            try {
                return Get().get(key);
            }
            catch (com.google.appengine.api.datastore.EntityNotFoundException notFound){
                return null;
            }
        }
        protected static Key Put(Entity entity){

            return Get().put(entity);
        }
        protected static void Delete(Key key){
            if (null != key){
                if (BigTable.IsAdmin(key.getKind())){

                    if (!Logon.IsAdmin())
                        throw new AdminAccessException(key.getKind());
                }
                Get().delete(new Key[]{key});
            }
        }
        /**
         * Defines query for keys only
         * @see BigTableIterator
         */
        protected static <T extends TableClass> BigTableIterator<T> QueryNClass(Query query, Page page){

            query.setKeysOnly();

            final PreparedQuery stmt = Get().prepare(query);

            return new BigTableIterator(stmt,page);
        }
        /**
         * Defines query for keys only
         * @see BigTableIterator
         */
        protected static <T extends TableClass> BigTableIterator<T> QueryNClass(Query query){

            query.setKeysOnly();

            final PreparedQuery stmt = Get().prepare(query);

            return new BigTableIterator(stmt);
        }
        protected static Key Query1(Query query){
            if (BigTable.IsAdmin(query.getKind())){

                if (!Logon.IsAdmin())
                    throw new AdminAccessException();
            }
            query.setKeysOnly();

            DatastoreService ds = Get();
            try {
                PreparedQuery stmt = ds.prepare(query);
                Entity entity = stmt.asSingleEntity();
                if (null == entity)
                    return null;
                else
                    return entity.getKey();
            }
            catch (com.google.appengine.api.datastore.PreparedQuery.TooManyResultsException exc){

                PreparedQuery stmt = ds.prepare(query);
                Key highKey = null;
                long highId = 0;
                for (Entity ent : stmt.asIterable()){
                    Key key = ent.getKey();
                    long keyId = key.getId();
                    if (keyId > highId){
                        highId = keyId;
                        highKey = key;
                    }
                }
                return highKey;
            }
        }
        protected static List.Primitive<Key> QueryN(Query query, Page page){
            if (BigTable.IsAdmin(query.getKind())){

                if (!Logon.IsAdmin())
                    throw new AdminAccessException();
            }
            query.setKeysOnly();

            DatastoreService ds = Get();
            PreparedQuery stmt = ds.prepare(query);

            Iterable<Entity> it = stmt.asIterable(page.createFetchOptions());

            List.Primitive<Key> list = new gap.util.ListPrimitiveKey(query.getKind());

            for (Entity entity : it){

                list.add(entity.getKey());
            }
            return list;
        }
        protected static List.Primitive<Key> QueryN(Query query){
            if (BigTable.IsAdmin(query.getKind())){

                if (!Logon.IsAdmin())
                    throw new AdminAccessException();
            }
            query.setKeysOnly();

            DatastoreService ds = Get();
            PreparedQuery stmt = ds.prepare(query);

            Iterable<Entity> it = stmt.asIterable();

            List.Primitive<Key> list = new gap.util.ListPrimitiveKey(query.getKind());

            for (Entity entity : it){

                list.add(entity.getKey());
            }
            return list;
        }
        protected static Iterable<Entity> QueryNUnbuffered(Query query){
            if (BigTable.IsAdmin(query.getKind())){

                if (!Logon.IsAdmin())
                    throw new AdminAccessException();
            }
            query.setKeysOnly();

            DatastoreService ds = Get();
            PreparedQuery stmt = ds.prepare(query);

            return stmt.asIterable();
        }
    }
    /**
     * Memcache
     */
    protected final static class C
        extends java.lang.Object
    {
        private final static ThreadLocal<MemcacheService> PTL = new ThreadLocal<MemcacheService>();


        protected static void Enter(String ns){
            MemcacheService ds = PTL.get();
            if (null == ds){
                ds = MemcacheServiceFactory.getMemcacheService();
                PTL.set(ds);
            }
            /*
             * Valid reentry is possible in some error handling schemes
             */
        }
        protected static void Exit(){
            PTL.remove();
        }
        protected static MemcacheService Get(){
            return PTL.get();
        }
        protected static Entity Get(Key key){
            try {
                final String ck = BigTable.ToString(key);
                final MemcacheService mc = Store.C.Get();
                try {
                    return (Entity)mc.get(ck);
                }
                catch (ClassCastException exc){
                    /*
                     * Code change conversion
                     */
                    mc.delete(key);
                    return null;
                }
                catch (com.google.appengine.api.memcache.InvalidValueException serialization){
                    mc.delete(key);
                    return null;
                }
            }
            catch (IllegalArgumentException incompleteKey){

                return null;
            }
        }
        protected static void Put(Key key, Entity entity){
            try {
                final String ck = BigTable.ToString(key,entity.getKey());

                Get().put(ck,entity);
            }
            catch (IllegalArgumentException incompleteKeys){
            }
        }
        protected static void Delete(Key key){

            if (null != key){
                try {
                    final String ck = BigTable.ToString(key);

                    Get().delete(ck);
                }
                catch (IllegalArgumentException incompleteKey){
                }
            }
        }
    }


    /**
     * Test enter without namespace (default application namespace)
     */
    public static void Test(){
        Store.Enter(null);
    }
    /**
     * Servlet init enter without namespace (default application namespace)
     */
    public static void EnterInit(){
        Store.Enter(null);
    }
    /**
     * Servlet service enter with namespace
     */
    public static void Enter(String ns){
        N.Enter(ns);
        P.Enter(ns);
        C.Enter(ns);
    }
    /**
     * Servlet exit
     */
    public static void Exit(){
        P.Exit();
        C.Exit();
    }
    public static String NS(){

        return N.Get();
    }
    public static <T extends TableClass> T GetClass(Key key){
        if (key.isComplete()){
            Entity entity = C.Get(key);
            if (null != entity){
                BigTable table = BigTable.From(entity);
                if (table instanceof AdminReadWrite){

                    if (!Logon.IsAdmin())
                        throw new AdminAccessException(table.getClassKind());
                }
                table.setFromMemcache();
                table.onread();
                return (T)table;
            }
            else {
                entity = P.Get(key);
                if (null != entity){
                    /*
                     * Optimistic cache
                     */
                    C.Put(key,entity);

                    BigTable table = BigTable.From(entity);
                    if (table instanceof AdminReadWrite){

                        if (!Logon.IsAdmin())
                            throw new AdminAccessException(table.getClassKind());
                    }
                    table.setFromDatastore();
                    table.onread();
                    return (T)table;
                }
                else
                    return null;
            }
        }
        else
            throw new IllegalArgumentException("Incomplete key '"+key+"'.");
    }
    public static Entity Get(Key key){
        if (key.isComplete()){
            Entity entity = C.Get(key);
            if (null != entity)
                return entity;
            else
                return P.Get(key);
        }
        else
            throw new IllegalArgumentException("Incomplete key '"+key+"'.");
    }
    public static <T extends TableClass> List<T> GetClass(Iterable<Key> keys){

        gap.util.ArrayList<T> list = new gap.util.ArrayList();

        for (Key key : keys){

            Entity entity = C.Get(key);
            if (null != entity){
                BigTable table = BigTable.From(entity);
                if (table instanceof AdminReadWrite){

                    if (!Logon.IsAdmin())
                        throw new AdminAccessException(table.getClassKind());
                }
                table.setFromMemcache();
                table.onread();
                list.add( (T)table);
            }
            else {
                entity = P.Get(key);
                if (null != entity){
                    /*
                     * Optimistic cache
                     */
                    C.Put(key,entity);

                    BigTable table = BigTable.From(entity);
                    if (table instanceof AdminReadWrite){

                        if (!Logon.IsAdmin())
                            throw new AdminAccessException(table.getClassKind());
                    }
                    table.setFromDatastore();
                    table.onread();
                    list.add( (T)table);
                }
            }
        }
        return list;
    }
    public static <T extends TableClass> T Query1Class(Query q){
        Key key = Store.P.Query1(q);
        if (null != key)
            return Store.GetClass(key);
        else
            return null;
    }
    public static <T extends TableClass> BigTableIterator<T> QueryNClass(Query q, Page p){

        if (null == p)
            return Store.P.QueryNClass(q);
        else
            return Store.P.QueryNClass(q,p);
    }
    public static <T extends TableClass> BigTableIterator<T> QueryNClass(Query q){

        return Store.P.QueryNClass(q);
    }
    public static Key Query1Key(Query q){

        return Store.P.Query1(q);
    }
    public static List.Primitive<Key> QueryNKey(Query q, Page p){

        if (null == p)
            return Store.P.QueryN(q);
        else
            return Store.P.QueryN(q,p);
    }
    public static List.Primitive<Key> QueryNKey(Query q){

        return Store.P.QueryN(q);
    }
    /**
     * Unbuffered for large sets
     *
     * @return Entities having only keys
     */
    public static Iterable<Entity> QueryNKeyUnbuffered(Query q){

        return Store.P.QueryNUnbuffered(q);
    }
    public static <T extends TableClass> T PutClass(T table){
        /*
         */
        if (table instanceof AdminReadWrite){

            if (!Logon.IsAdmin())
                throw new AdminAccessException(table.getClassKind());
        }
        else if (table instanceof LastModified){
            ((LastModified)table).setLastModified(System.currentTimeMillis());
        }

        table.onwrite();

        Key key = table.getKey();

        final Lock lock = Lock.Accept(key);
        if (lock.accept()){
            try {
                /*
                 * Current clean
                 */
                Entity entity = Store.Get(key);

                if (null == entity){

                    entity = new Entity(key);

                    table.markDirty();
                    /*
                     * Copy all
                     */
                    table.fillTo(entity);
                }
                else {
                    /*
                     * Write dirty (push changes local dirty)
                     */
                    table.fillTo(entity);
                    /*
                     * Read clean (pull changes not local dirty)
                     */
                    table.fillFrom(entity);
                }
                table.markClean();

                key = P.Put(entity);
                /*
                 * Copy write to cache
                 */
                C.Put(key,entity);

                table.setKey(key);

                return table;
            }
            finally {
                lock.exit();
            }
        }
        else
            throw new IllegalArgumentException("Failed to acquire write lock");
    }
    public static void Delete(Key key){
        final Lock lock = Lock.Accept(key);
        if (lock.accept()){
            try {
                C.Delete(key);
                P.Delete(key);
            }
            finally {
                lock.exit();
            }
        }
        else
            throw new IllegalArgumentException("Failed to acquire write lock");
    }
    public static void Clean(Key key){
        C.Delete(key);
    }
    public static void DeleteCollection(Kind access, Query query){
        if (BigTable.IsAdmin(access)){

            if (!Logon.IsAdmin())
                throw new AdminAccessException(access);
        }
        query.setKeysOnly();

        final DatastoreService ds = Store.P.Get();
        final MemcacheService mc = Store.C.Get();

        PreparedQuery stmt = ds.prepare(query);

        Iterable<Entity> list = stmt.asIterable();

        for (Entity ent : list){
            final Key key = ent.getKey();
            final Lock lock = new Lock(key);
            if (lock.enter()){
                try {
                    mc.delete(BigTable.ToString(key));

                    ds.delete(key);
                }
                catch (RuntimeException any){
                }
                finally {
                    lock.exit();
                }
            }
        }
    }


    private Store(){
        super();
    }
}
TOP

Related Classes of gap.data.Store$C

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.