Package com.hazelcast.map.mapstore.writebehind

Source Code of com.hazelcast.map.mapstore.writebehind.WriteBehindWithEntryProcessorTest$Subscription

package com.hazelcast.map.mapstore.writebehind;

import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.core.IMap;
import com.hazelcast.core.MapStore;
import com.hazelcast.core.MapStoreAdapter;
import com.hazelcast.map.AbstractEntryProcessor;
import com.hazelcast.test.AssertTask;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import static org.junit.Assert.assertEquals;

@RunWith(HazelcastParallelClassRunner.class)
@Category(QuickTest.class)
public class WriteBehindWithEntryProcessorTest extends HazelcastTestSupport {

    @Test
    public void updates_on_same_key_when_in_memory_format_is_object() throws Exception {
        final long customerId = 0L;
        final int numberOfSubscriptions = 1000;
        final MapStore mapStore = new DataStore();
        final IMap<Long, Customer> map = createMap(mapStore);

        addCustomer(map, customerId);

        // add subscriptions.
        addSubscriptions(map, customerId, numberOfSubscriptions);

        // remove half of subscriptions.
        removeSubscriptions(map, customerId, numberOfSubscriptions / 2);

        assertAllSubscriptionsInStore(mapStore, numberOfSubscriptions / 2);
        assertStoreCallCount(mapStore, 1);
    }

    private IMap<Long, Customer> createMap(MapStore mapStore) {
        final TestMapUsingMapStoreBuilder builder = TestMapUsingMapStoreBuilder.create()
                .withMapStore(mapStore)
                .withNodeCount(1)
                .withBackupCount(0)
                .withWriteDelaySeconds(3)
                .withInMemoryFormat(InMemoryFormat.OBJECT);
        return builder.build();
    }

    private void assertAllSubscriptionsInStore(MapStore mapStore, final int numberOfSubscriptions) {
        final DataStore store = (DataStore) mapStore;
        assertTrueEventually(new AssertTask() {
            @Override
            public void run() throws Exception {
                assertEquals(numberOfSubscriptions, store.subscriptionCount());
            }
        }, 20);
    }

    private void assertStoreCallCount(MapStore mapStore, final int expectedStoreCallcount) {
        final DataStore store = (DataStore) mapStore;
        final int storeCallCount = store.getStoreCallCount();
        assertEquals(expectedStoreCallcount, storeCallCount);
    }

    private void addSubscriptions(IMap map, long customerId, int numberOfSubscriptions) {
        for (long i = 0; i < numberOfSubscriptions; i++) {
            addSubscription(map, customerId, i);
        }
    }

    private void removeSubscriptions(IMap map, long customerId, int numberOfSubscriptions) {
        for (long i = 0; i < numberOfSubscriptions; i++) {
            removeSubscription(map, customerId, i);
        }
    }

    private void addSubscription(IMap map, long customerId, final long productId) {
        map.executeOnKey(customerId, new AbstractEntryProcessor() {
            @Override
            public Object process(Map.Entry entry) {
                final Customer customer = (Customer) entry.getValue();
                customer.addSubscription(new Subscription(productId, false));
                entry.setValue(customer);
                return customer.getSubscriptions().size();
            }
        });
    }

    private void removeSubscription(IMap map, long customerId, final long productId) {
        map.executeOnKey(customerId, new AbstractEntryProcessor() {
            @Override
            public Object process(Map.Entry entry) {
                final Customer customer = (Customer) entry.getValue();
                customer.removeSubscription(productId);
                entry.setValue(customer);
                return customer.getSubscriptions().size();
            }
        });
    }


    private void addCustomer(IMap map, long customerId) {
        final Customer customer = new Customer(customerId);
        map.put(Long.valueOf(customerId), customer);
    }


    private static class DataStore extends MapStoreAdapter<Long, Customer> {

        private AtomicInteger storeCallCount;
        private final Map<Long, List<Subscription>> store;

        private DataStore() {
            store = new ConcurrentHashMap<Long, List<Subscription>>();
            storeCallCount = new AtomicInteger(0);
        }

        @Override
        public void store(Long key, Customer customer) {
            storeCallCount.incrementAndGet();
            final List<Subscription> subscriptions = customer.getSubscriptions();
            for (Subscription subscription : subscriptions) {
                if (!subscription.isVerified()) {
                    List<Subscription> list = store.get(key);
                    if (list == null) {
                        list = new ArrayList<Subscription>();
                        store.put(key, list);
                    }
                    subscription.setVerified(true);
                    list.add(subscription);
                }
            }
        }

        public int subscriptionCount() {
            final List<Subscription> list = store.get(0L);
            return list == null ? 0 : list.size();
        }

        public int getStoreCallCount() {
            return storeCallCount.get();
        }
    }


    private static class Customer implements Serializable {

        private long customerId;
        private List<Subscription> subscriptions;

        private Customer() {
        }

        private Customer(long customerId) {
            this.customerId = customerId;
        }

        public void addSubscription(Subscription subscription) {
            if (subscriptions == null) {
                subscriptions = new ArrayList<Subscription>();
            }
            subscriptions.add(subscription);
        }

        public void removeSubscription(long productId) {
            if (subscriptions == null || subscriptions.isEmpty()) {
                return;
            }
            final Iterator<Subscription> iterator = subscriptions.iterator();
            while (iterator.hasNext()) {
                final Subscription next = iterator.next();
                if (next.getProductId() == productId) {
                    iterator.remove();
                    break;
                }
            }
        }

        public List<Subscription> getSubscriptions() {
            return subscriptions;
        }

        public void setSubscriptions(List<Subscription> subscriptions) {
            this.subscriptions = subscriptions;
        }

        public long getCustomerId() {
            return customerId;
        }

        public void setCustomerId(long customerId) {
            this.customerId = customerId;
        }
    }

    private static class Subscription implements Serializable {
        private long productId;
        private boolean verified;

        private Subscription(long productId, boolean verified) {
            this.productId = productId;
            this.verified = verified;
        }

        public long getProductId() {
            return productId;
        }

        public void setProductId(long productId) {
            this.productId = productId;
        }

        public boolean isVerified() {
            return verified;
        }

        public void setVerified(boolean verified) {
            this.verified = verified;
        }

        @Override
        public String toString() {
            return "Subscription{"
                    + "productId=" + productId
                    + ", verified=" + verified
                    + '}';
        }
    }
}
TOP

Related Classes of com.hazelcast.map.mapstore.writebehind.WriteBehindWithEntryProcessorTest$Subscription

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.