All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.map.impl.mapstore.writebehind.CoalescedWriteBehindQueue Maven / Gradle / Ivy

There is a newer version: 5.0-BETA-1
Show newest version
/*
 * Copyright (c) 2008-2015, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed 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.hazelcast.map.impl.mapstore.writebehind;

import com.hazelcast.map.impl.mapstore.writebehind.entry.DelayedEntry;
import com.hazelcast.nio.serialization.Data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static com.hazelcast.util.CollectionUtil.isEmpty;
import static com.hazelcast.util.Preconditions.checkNotNull;

/**
 * A write-behind queue which supports write coalescing.
 */
class CoalescedWriteBehindQueue implements WriteBehindQueue {

    protected Map map;

    public CoalescedWriteBehindQueue() {
        map = new LinkedHashMap();
    }

    @Override
    public void addFirst(Collection collection) {
        if (isEmpty(collection)) {
            return;
        }
        int expectedCapacity = map.size() + collection.size();
        Map newMap = createMapWithExpectedCapacity(expectedCapacity);
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            DelayedEntry next = iterator.next();
            newMap.put((Data) next.getKey(), next);
        }
        newMap.putAll(map);
        map = newMap;
    }

    @Override
    public void addLast(DelayedEntry delayedEntry) {
        if (delayedEntry == null) {
            return;
        }
        calculateStoreTime(delayedEntry);
        Data key = (Data) delayedEntry.getKey();
        map.put(key, delayedEntry);
    }

    /**
     * Removes the first occurrence of the specified element in this queue
     * when searching it by starting from the head of this queue.
     *
     * @param entry element to be removed.
     * @return true if removed successfully, false otherwise
     */
    @Override
    public boolean removeFirstOccurrence(DelayedEntry entry) {
        Data key = (Data) entry.getKey();
        Object value = entry.getValue();
        DelayedEntry delayedEntry = map.get(key);
        if (delayedEntry == null) {
            return false;
        }
        Object existingValue = delayedEntry.getValue();
        if (existingValue == value) {
            map.remove(key);
            return true;
        }

        return false;
    }

    @Override
    public boolean contains(DelayedEntry entry) {
        //noinspection SuspiciousMethodCalls
        return map.containsKey(entry.getKey());
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public void clear() {
        map.clear();
    }

    @Override
    public int drainTo(Collection collection) {
        checkNotNull(collection, "collection can not be null");

        Collection delayedEntries = map.values();
        for (DelayedEntry delayedEntry : delayedEntries) {
            collection.add(delayedEntry);
        }
        map.clear();
        return collection.size();
    }

    @Override
    public List asList() {
        Collection values = map.values();
        return Collections.unmodifiableList(new ArrayList(values));
    }


    @Override
    public void getFrontByTime(long time, Collection collection) {
        Collection values = map.values();
        for (DelayedEntry e : values) {
            if (e.getStoreTime() <= time) {
                collection.add(e);
            }
        }
    }

    @Override
    public void getFrontByNumber(int numberOfElements, Collection collection) {
        int count = 0;
        Collection values = map.values();
        for (DelayedEntry e : values) {
            if (count == numberOfElements) {
                break;
            }
            collection.add(e);
            count++;
        }
    }


    /**
     * If this is an existing key in this queue, use previously set store time;
     * since we do not want to shift store time of an existing key on every update.
     */
    private void calculateStoreTime(DelayedEntry delayedEntry) {
        Data key = (Data) delayedEntry.getKey();
        DelayedEntry currentEntry = map.get(key);
        if (currentEntry != null) {
            long currentStoreTime = currentEntry.getStoreTime();
            delayedEntry.setStoreTime(currentStoreTime);
        }
    }

    private static  Map createMapWithExpectedCapacity(int expectedCapacity) {
        final double defaultLoadFactor = 0.75;
        int initialCapacity = (int) (expectedCapacity / defaultLoadFactor) + 1;
        return new LinkedHashMap(initialCapacity);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy