Package org.sdnplatform.sync.internal

Source Code of org.sdnplatform.sync.internal.DefaultStoreClient

package org.sdnplatform.sync.internal;

import java.util.List;
import java.util.Map.Entry;

import com.fasterxml.jackson.core.type.TypeReference;

import org.sdnplatform.sync.IClosableIterator;
import org.sdnplatform.sync.IInconsistencyResolver;
import org.sdnplatform.sync.IStoreListener;
import org.sdnplatform.sync.IVersion;
import org.sdnplatform.sync.Versioned;
import org.sdnplatform.sync.error.InconsistentDataException;
import org.sdnplatform.sync.error.SyncException;
import org.sdnplatform.sync.error.UnknownStoreException;
import org.sdnplatform.sync.internal.store.IStore;
import org.sdnplatform.sync.internal.store.MappingStoreListener;
import org.sdnplatform.sync.internal.util.Pair;
import org.sdnplatform.sync.internal.version.ChainedResolver;
import org.sdnplatform.sync.internal.version.TimeBasedInconsistencyResolver;
import org.sdnplatform.sync.internal.version.VectorClock;
import org.sdnplatform.sync.internal.version.VectorClockInconsistencyResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
* Default implementation of a store client used for accessing a store
* locally in process.
* @author readams
*
* @param <K> the key type
* @param <V> the value type
*/
public class DefaultStoreClient<K, V> extends AbstractStoreClient<K, V> {
    protected static final Logger logger =
            LoggerFactory.getLogger(DefaultStoreClient.class.getName());

    private IStore<K, V> delegate;
    private IInconsistencyResolver<Versioned<V>> resolver;
    private AbstractSyncManager syncManager;
    private Class<K> keyClass;
    private TypeReference<K> keyType;

    @SuppressWarnings("unchecked")
    public DefaultStoreClient(IStore<K, V> delegate,
                              IInconsistencyResolver<Versioned<V>> resolver,
                              AbstractSyncManager syncManager,
                              Class<K> keyClass,
                              TypeReference<K> keyType) {
        super();
        this.delegate = delegate;
        this.syncManager = syncManager;
        this.keyClass = keyClass;
        this.keyType = keyType;
       
        IInconsistencyResolver<Versioned<V>> vcir =
                new VectorClockInconsistencyResolver<V>();
        IInconsistencyResolver<Versioned<V>> secondary = resolver;
        if (secondary == null)
            secondary = new TimeBasedInconsistencyResolver<V>();
        this.resolver = new ChainedResolver<Versioned<V>>(vcir, secondary);
    }

    // ******************
    // IStoreClient<K,V>
    // ******************

    @Override
    public Versioned<V> get(K key, Versioned<V> defaultValue)
            throws SyncException {
        List<Versioned<V>> raw = delegate.get(key);
        return handleGet(key, defaultValue, raw);
    }

    @Override
    public IClosableIterator<Entry<K, Versioned<V>>> entries() throws SyncException {
        return new StoreClientIterator(delegate.entries());
    }

    @Override
    public IVersion put(K key, Versioned<V> versioned)
            throws SyncException {
        VectorClock vc = (VectorClock)versioned.getVersion();

        vc = vc.incremented(syncManager.getLocalNodeId(),
                            System.currentTimeMillis());
        versioned = Versioned.value(versioned.getValue(), vc);

        delegate.put(key, versioned);
        return versioned.getVersion();
    }

    @Override
    public void addStoreListener(IStoreListener<K> listener) {
        if (listener == null)
            throw new IllegalArgumentException("Must include listener");
        MappingStoreListener msl =
                new MappingStoreListener(keyType, keyClass, listener);
        try {
            syncManager.addListener(delegate.getName(), msl);
        } catch (UnknownStoreException e) {
            // this shouldn't happen since we already have a store client,
            // unless the store has been deleted somehow
            logger.error("Unexpected internal state: unknown store " +
                         "from store client.  Could not register listener", e);
        }
    }

    // ************************
    // AbstractStoreClient<K,V>
    // ************************

    @Override
    protected List<IVersion> getVersions(K key) throws SyncException {
        return delegate.getVersions(key);
    }

    // *********************
    // Private local methods
    // *********************

    protected Versioned<V> handleGet(K key,
                                     Versioned<V> defaultValue,
                                     List<Versioned<V>> raw)
                                             throws InconsistentDataException {
        if (raw == null) return defaultValue(defaultValue);
        List<Versioned<V>> vs = resolver.resolveConflicts(raw);
        return getItemOrThrow(key, defaultValue, vs);
    }
   
    protected Versioned<V> defaultValue(Versioned<V> defaultValue) {
        if (defaultValue == null)
            return Versioned.emptyVersioned();
        return defaultValue;
    }
   
    protected Versioned<V> getItemOrThrow(K key,
                                          Versioned<V> defaultValue,
                                          List<Versioned<V>> items)
             throws InconsistentDataException {
        if(items.size() == 0)
            return defaultValue(defaultValue);
        else if(items.size() == 1)
            return items.get(0);
        else
            throw new InconsistentDataException("Resolver failed to resolve" +
                    " conflict: " + items.size() + " unresolved items", items);
    }
   
   
    protected class StoreClientIterator implements
        IClosableIterator<Entry<K, Versioned<V>>> {

        IClosableIterator<Entry<K, List<Versioned<V>>>> delegate;
       
        public StoreClientIterator(IClosableIterator<Entry<K,
                                   List<Versioned<V>>>> delegate) {
            super();
            this.delegate = delegate;
        }

        @Override
        public boolean hasNext() {
            return delegate.hasNext();
        }

        @Override
        public Entry<K, Versioned<V>> next() {
            Entry<K, List<Versioned<V>>> n = delegate.next();
            try {
                return new Pair<K, Versioned<V>>(n.getKey(),
                                      handleGet(n.getKey(), null, n.getValue()));
            } catch (SyncException e) {
                logger.error("Failed to construct next value", e);
                return null;
            }
        }

        @Override
        public void remove() {
            delegate.remove();
        }

        @Override
        public void close() {
            delegate.close();
        }
       
    }
}
TOP

Related Classes of org.sdnplatform.sync.internal.DefaultStoreClient

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.
m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-20639858-1', 'auto'); ga('send', 'pageview');