/*
 * 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 com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.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;
import org.apache.cassandra.utils.FBUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import com.google.common.util.concurrent.MoreExecutors;

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

    private final Cache<K, RefCountedMemory> cache;
    private final ISerializer<V> serializer;

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

        this.cache = Caffeine.newBuilder()
                   .weigher(weigher)
                   .maximumWeight(capacity)
                   .executor(MoreExecutors.directExecutor())
                   .removalListener((key, mem, cause) -> {
                       if (cause.wasEvicted()) {
                           mem.unreference();
                       }
                   })
                   .build();
    }

    public static <K, V> SerializingCache<K, V> create(long weightedCapacity, Weigher<K, 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, (key, value) -> {
            long size = value.size();
            if (size > Integer.MAX_VALUE) {
                throw new IllegalArgumentException("Serialized size must not be more than 2GB");
            }
            return (int) size;
        }, serializer);
    }

    @SuppressWarnings("resource")
    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;
        }
    }

    @SuppressWarnings("resource")
    private RefCountedMemory serialize(V value)
    {
        long serializedSize = serializer.serializedSize(value);
        if (serializedSize > Integer.MAX_VALUE)
            throw new IllegalArgumentException(String.format("Unable to allocate %s", FBUtilities.prettyPrintMemory(serializedSize)));

        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 cache.policy().eviction().get().getMaximum();
    }

    public void setCapacity(long capacity)
    {
        cache.policy().eviction().get().setMaximum(capacity);
    }

    public boolean isEmpty()
    {
        return cache.asMap().isEmpty();
    }

    public int size()
    {
        return cache.asMap().size();
    }

    public long weightedSize()
    {
        return cache.policy().eviction().get().weightedSize().getAsLong();
    }

    public void clear()
    {
        cache.invalidateAll();
    }

    @SuppressWarnings("resource")
    public V get(K key)
    {
        RefCountedMemory mem = cache.getIfPresent(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 = cache.asMap().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 = cache.asMap().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 cache, we fail
        RefCountedMemory old = cache.getIfPresent(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 = cache.asMap().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 = cache.asMap().remove(key);
        if (mem != null)
            mem.unreference();
    }

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

    public Iterator<K> hotKeyIterator(int n)
    {
        return cache.policy().eviction().get().hottest(n).keySet().iterator();
    }

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