/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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 org.apache.cassandra.cache;

import java.io.IOException;
import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.EvictionListener;
import com.googlecode.concurrentlinkedhashmap.Weigher;

import org.apache.cassandra.io.ISerializer;
import org.apache.cassandra.io.util.MemoryInputStream;
import org.apache.cassandra.io.util.MemoryOutputStream;
import org.apache.cassandra.io.util.WrappedDataOutputStreamPlus;

/**
 * Serializes cache values off-heap.
 */
public class SerializingCache<K, V> implements ICache<K, V>
{
    private static final Logger logger = LoggerFactory.getLogger(SerializingCache.class);

    private static final int DEFAULT_CONCURENCY_LEVEL = 64;

    private final ConcurrentLinkedHashMap<K, RefCountedMemory> map;
    private final ISerializer<V> serializer;

    private SerializingCache(long capacity, Weigher<RefCountedMemory> weigher, ISerializer<V> serializer)
    {
        this.serializer = serializer;

        EvictionListener<K,RefCountedMemory> listener = new EvictionListener<K, RefCountedMemory>()
        {
            public void onEviction(K k, RefCountedMemory mem)
            {
                mem.unreference();
            }
        };

        this.map = new ConcurrentLinkedHashMap.Builder<K, RefCountedMemory>()
                   .weigher(weigher)
                   .maximumWeightedCapacity(capacity)
                   .concurrencyLevel(DEFAULT_CONCURENCY_LEVEL)
                   .listener(listener)
                   .build();
    }

    public static <K, V> SerializingCache<K, V> create(long weightedCapacity, Weigher<RefCountedMemory> weigher, ISerializer<V> serializer)
    {
        return new SerializingCache<>(weightedCapacity, weigher, serializer);
    }

    public static <K, V> SerializingCache<K, V> create(long weightedCapacity, ISerializer<V> serializer)
    {
        return create(weightedCapacity, new Weigher<RefCountedMemory>()
        {
            public int weightOf(RefCountedMemory value)
            {
                long size = value.size();
                assert size < Integer.MAX_VALUE : "Serialized size cannot be more than 2GB";
                return (int) size;
            }
        }, serializer);
    }

    private V deserialize(RefCountedMemory mem)
    {
        try
        {
            return serializer.deserialize(new MemoryInputStream(mem));
        }
        catch (IOException e)
        {
            logger.trace("Cannot fetch in memory data, we will fallback to read from disk ", e);
            return null;
        }
    }

    private RefCountedMemory serialize(V value)
    {
        long serializedSize = serializer.serializedSize(value);
        if (serializedSize > Integer.MAX_VALUE)
            throw new IllegalArgumentException("Unable to allocate " + serializedSize + " bytes");

        RefCountedMemory freeableMemory;
        try
        {
            freeableMemory = new RefCountedMemory(serializedSize);
        }
        catch (OutOfMemoryError e)
        {
            return null;
        }

        try
        {
            serializer.serialize(value, new WrappedDataOutputStreamPlus(new MemoryOutputStream(freeableMemory)));
        }
        catch (IOException e)
        {
            freeableMemory.unreference();
            throw new RuntimeException(e);
        }
        return freeableMemory;
    }

    public long capacity()
    {
        return map.capacity();
    }

    public void setCapacity(long capacity)
    {
        map.setCapacity(capacity);
    }

    public boolean isEmpty()
    {
        return map.isEmpty();
    }

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

    public long weightedSize()
    {
        return map.weightedSize();
    }

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

    @SuppressWarnings("resource")
    public V get(K key)
    {
        RefCountedMemory mem = map.get(key);
        if (mem == null)
            return null;
        if (!mem.reference())
            return null;
        try
        {
            return deserialize(mem);
        }
        finally
        {
            mem.unreference();
        }
    }

    @SuppressWarnings("resource")
    public void put(K key, V value)
    {
        RefCountedMemory mem = serialize(value);
        if (mem == null)
            return; // out of memory.  never mind.

        RefCountedMemory old;
        try
        {
            old = map.put(key, mem);
        }
        catch (Throwable t)
        {
            mem.unreference();
            throw t;
        }

        if (old != null)
            old.unreference();
    }

    @SuppressWarnings("resource")
    public boolean putIfAbsent(K key, V value)
    {
        RefCountedMemory mem = serialize(value);
        if (mem == null)
            return false; // out of memory.  never mind.

        RefCountedMemory old;
        try
        {
            old = map.putIfAbsent(key, mem);
        }
        catch (Throwable t)
        {
            mem.unreference();
            throw t;
        }

        if (old != null)
            // the new value was not put, we've uselessly allocated some memory, free it
            mem.unreference();
        return old == null;
    }

    @SuppressWarnings("resource")
    public boolean replace(K key, V oldToReplace, V value)
    {
        // if there is no old value in our map, we fail
        RefCountedMemory old = map.get(key);
        if (old == null)
            return false;

        V oldValue;
        // reference old guy before de-serializing
        if (!old.reference())
            return false; // we have already freed hence noop.

        oldValue = deserialize(old);
        old.unreference();

        if (!oldValue.equals(oldToReplace))
            return false;

        // see if the old value matches the one we want to replace
        RefCountedMemory mem = serialize(value);
        if (mem == null)
            return false; // out of memory.  never mind.

        boolean success;
        try
        {
            success = map.replace(key, old, mem);
        }
        catch (Throwable t)
        {
            mem.unreference();
            throw t;
        }

        if (success)
            old.unreference(); // so it will be eventually be cleaned
        else
            mem.unreference();
        return success;
    }

    public void remove(K key)
    {
        @SuppressWarnings("resource")
        RefCountedMemory mem = map.remove(key);
        if (mem != null)
            mem.unreference();
    }

    public Iterator<K> keyIterator()
    {
        return map.keySet().iterator();
    }

    public Iterator<K> hotKeyIterator(int n)
    {
        return map.descendingKeySetWithLimit(n).iterator();
    }

    public boolean containsKey(K key)
    {
        return map.containsKey(key);
    }
}
