com.caricah.iotracah.datastore.ignitecache.internal.AbstractHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.caricah.iotracah.datastore.ignitecache.internal.AbstractHandler.java

Source

/*
 *
 * Copyright (c) 2015 Caricah <info@caricah.com>.
 *
 * Caricah licenses this file to you under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. You may obtain a copy
 *  of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under
 *  the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
 *  OF ANY  KIND, either express or implied.  See the License for the specific language
 *  governing permissions and limitations under the License.
 *
 *
 *
 *
 */

package com.caricah.iotracah.datastore.ignitecache.internal;

import com.caricah.iotracah.bootstrap.data.models.client.IotClientKey;
import com.caricah.iotracah.bootstrap.exceptions.UnRetriableException;
import com.caricah.iotracah.bootstrap.security.realm.state.IOTClient;
import com.caricah.iotracah.core.worker.exceptions.DoesNotExistException;
import org.apache.commons.configuration.Configuration;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteAtomicSequence;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMemoryMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.cache.eviction.lru.LruEvictionPolicy;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.SqlQuery;
import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory;
import org.apache.ignite.configuration.CacheConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.Scheduler;
import rx.schedulers.Schedulers;

import javax.cache.Cache.Entry;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;

/**
 * @author <a href="mailto:bwire@caricah.com"> Peter Bwire </a>
 * @version 1.0 9/20/15
 */
public abstract class AbstractHandler<K, T> implements Serializable {

    protected final Logger log = LoggerFactory.getLogger(getClass());

    private String cacheName;
    private IgniteCache<K, T> datastoreCache;

    private IgniteAtomicSequence idSequence;

    private Scheduler scheduler;

    private ExecutorService executorService;

    private Class<T> classType;

    private boolean persistanceEnabled;

    public String getCacheName() {
        return cacheName;
    }

    public void setCacheName(String cacheName) {
        this.cacheName = cacheName;
    }

    public boolean isPersistanceEnabled() {
        return persistanceEnabled;
    }

    public void setPersistanceEnabled(boolean persistanceEnabled) {
        this.persistanceEnabled = persistanceEnabled;
    }

    public IgniteCache<K, T> getDatastoreCache() {
        return datastoreCache;
    }

    public void setDatastoreCache(IgniteCache<K, T> datastoreCache) {
        this.datastoreCache = datastoreCache;
    }

    public IgniteAtomicSequence getIdSequence() {
        return idSequence;
    }

    public void setIdSequence(IgniteAtomicSequence idSequence) {
        this.idSequence = idSequence;
    }

    public Scheduler getScheduler() {
        return scheduler;
    }

    public void setScheduler() {
        this.scheduler = Schedulers.from(getExecutorService());
    }

    public ExecutorService getExecutorService() {
        return executorService;
    }

    public void setExecutorService(ExecutorService executorService) {
        this.executorService = executorService;

        setScheduler();
    }

    public abstract void configure(Configuration configuration);

    public void initiate(Class<T> t, Ignite ignite) {

        try {
            Context ic = new InitialContext();

            DataSource dataSource;
            if (isPersistanceEnabled())
                dataSource = (DataSource) ic.lookup("jdbc_commonpool");
            else
                dataSource = null;

            CacheConfiguration<K, T> clCfg = getCacheConfiguration(isPersistanceEnabled(), dataSource);

            clCfg = extraCacheSettingsConfigure(clCfg);

            ignite.createCache(clCfg);
            IgniteCache<K, T> clientIgniteCache = ignite.cache(getCacheName());

            clientIgniteCache.loadCache(null);

            setDatastoreCache(clientIgniteCache);

            classType = t;

            String nameOfSequence = getCacheName() + "-sequence";
            initializeSequence(nameOfSequence, ignite);

        } catch (NamingException e) {
            log.error(" getFactory : problems obtaining appropriate jdbc context");
            throw new UnRetriableException(e);
        }

    }

    private CacheConfiguration<K, T> extraCacheSettingsConfigure(CacheConfiguration<K, T> clCfg) {

        clCfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);

        clCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC);
        clCfg.setCacheMode(CacheMode.PARTITIONED);

        clCfg.setMemoryMode(CacheMemoryMode.ONHEAP_TIERED);
        clCfg.setOffHeapMaxMemory(0);

        LruEvictionPolicy lruEvictionPolicy = new LruEvictionPolicy(5170000);
        clCfg.setEvictionPolicy(lruEvictionPolicy);

        clCfg.setSwapEnabled(false);
        clCfg.setRebalanceBatchSize(1024 * 1024);
        clCfg.setRebalanceThrottle(0);
        clCfg.setRebalanceThreadPoolSize(4);

        return clCfg;

    }

    protected abstract CacheConfiguration<K, T> getCacheConfiguration(boolean persistanceEnabled, DataSource ds);

    public void initializeSequence(String nameOfSequence, Ignite ignite) {

        long currentTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
        IgniteAtomicSequence idSequence = ignite.atomicSequence(nameOfSequence, currentTime, true);
        setIdSequence(idSequence);
    }

    public Observable<T> getByKey(K key) {

        return Observable.create(observer -> {

            try {
                // do work on separate thread
                T actualResult = getDatastoreCache().get(key);

                if (Objects.nonNull(actualResult)) {
                    observer.onNext(actualResult);
                    observer.onCompleted();
                } else {
                    observer.onError(new DoesNotExistException(
                            String.format("%s with key [%s] does not exist.", classType, key)));
                }

            } catch (Exception e) {
                observer.onError(e);
            }

        });

    }

    public Observable<T> getBySet(Set<K> keys) {

        return Observable.create(observer -> {

            try {

                keys.forEach(

                        key -> {

                            T item = getDatastoreCache().get(key);

                            if (Objects.nonNull(item))
                                observer.onNext(item);

                        });

                observer.onCompleted();

            } catch (Exception e) {
                observer.onError(e);
            }

        });

    }

    public Observable<T> getByKeyWithDefault(K key, T defaultValue) {

        return Observable.create(observer -> {

            try {
                // do work on separate thread

                T value = getDatastoreCache().get(key);
                // callback with value only if not null
                if (null != value) {
                    observer.onNext(value);
                } else {
                    observer.onNext(defaultValue);
                }
                observer.onCompleted();

            } catch (Exception e) {
                observer.onError(e);
            }

        });

    }

    public Observable<T> getByQuery(Class<T> t, String query, Object[] params) {

        return Observable.create(observer -> {

            try {

                SqlQuery sql = new SqlQuery<Serializable, T>(t, query);
                sql.setArgs(params);

                // Find all messages belonging to a client.
                QueryCursor<Entry<K, T>> queryResult = getDatastoreCache().query(sql);

                for (Entry<K, T> entry : queryResult) {
                    // callback with value
                    observer.onNext(entry.getValue());
                }

                observer.onCompleted();
            } catch (Exception e) {
                observer.onError(e);
            }

        });

    }

    public <L extends Serializable> Observable<L> getByQueryAsValue(Class<L> l, String query, Object[] params) {

        return Observable.create(observer -> {
            try {

                SqlFieldsQuery sql = new SqlFieldsQuery(query);

                // Execute the query and obtain the query result cursor.
                try (QueryCursor<List<?>> queryResult = getDatastoreCache().query(sql.setArgs(params))) {
                    // callback with value

                    for (List entry : queryResult) {
                        // callback with value
                        observer.onNext((L) entry.get(0));
                    }

                }

                observer.onCompleted();
            } catch (Exception e) {
                observer.onError(e);
            }
        });

    }

    public abstract K keyFromModel(T model);

    public void save(T item) {
        save(keyFromModel(item), item);
    }

    protected void save(K key, T item) {

        try {

            getDatastoreCache().put(key, item);

        } catch (Exception e) {
            log.error(" save : issues while saving item ", e);
        }

    }

    public void remove(T item) {
        removeByKey(keyFromModel(item));
    }

    protected void removeByKey(K item) {

        try {
            getDatastoreCache().remove(item);
        } catch (Exception e) {
            log.error(" remove : problem while removing item ", e);
        }

    }

}