/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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 java.net;

import dalvik.annotation.compat.UnsupportedAppUsage;
import libcore.util.BasicLruCache;

/**
 * Implements caching for {@code InetAddress}. We use a unified cache for both positive and negative
 * cache entries.
 *
 * TODO: benchmark and optimize InetAddress until we get to the point where we can just rely on
 * the C library level caching. The main thing caching at this level buys us is avoiding repeated
 * conversions from 'struct sockaddr's to InetAddress[].
 */
class AddressCache {
    /**
     * When the cache contains more entries than this, we start dropping the oldest ones.
     * This should be a power of two to avoid wasted space in our custom map.
     */
    private static final int MAX_ENTRIES = 16;

    // The TTL for the Java-level cache is short, just 2s.
    private static final long TTL_NANOS = 2 * 1000000000L;

    // The actual cache.
    @UnsupportedAppUsage
    private final BasicLruCache<AddressCacheKey, AddressCacheEntry> cache
            = new BasicLruCache<AddressCacheKey, AddressCacheEntry>(MAX_ENTRIES);

    static class AddressCacheKey {
        @UnsupportedAppUsage
        private final String mHostname;
        private final int mNetId;

        AddressCacheKey(String hostname, int netId) {
            mHostname = hostname;
            mNetId = netId;
        }

        @Override public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (!(o instanceof AddressCacheKey)) {
                return false;
            }
            AddressCacheKey lhs = (AddressCacheKey) o;
            return mHostname.equals(lhs.mHostname) && mNetId == lhs.mNetId;
        }

        @Override public int hashCode() {
            int result = 17;
            result = 31 * result + mNetId;
            result = 31 * result + mHostname.hashCode();
            return result;
        }
    }

    static class AddressCacheEntry {
        // Either an InetAddress[] for a positive entry,
        // or a String detail message for a negative entry.
        @UnsupportedAppUsage
        final Object value;

        /**
         * The absolute expiry time in nanoseconds. Nanoseconds from System.nanoTime is ideal
         * because -- unlike System.currentTimeMillis -- it can never go backwards.
         *
         * We don't need to worry about overflow with a TTL_NANOS of 2s.
         */
        @UnsupportedAppUsage
        final long expiryNanos;

        @UnsupportedAppUsage
        AddressCacheEntry(Object value) {
            this.value = value;
            this.expiryNanos = System.nanoTime() + TTL_NANOS;
        }
    }

    /**
     * Removes all entries from the cache.
     */
    public void clear() {
        cache.evictAll();
    }

    /**
     * Returns the cached InetAddress[] for 'hostname' on network 'netId'. Returns null
     * if nothing is known about 'hostname'. Returns a String suitable for use as an
     * UnknownHostException detail message if 'hostname' is known not to exist.
     */
    public Object get(String hostname, int netId) {
        AddressCacheEntry entry = cache.get(new AddressCacheKey(hostname, netId));
        // Do we have a valid cache entry?
        if (entry != null && entry.expiryNanos >= System.nanoTime()) {
            return entry.value;
        }
        // Either we didn't find anything, or it had expired.
        // No need to remove expired entries: the caller will provide a replacement shortly.
        return null;
    }

    /**
     * Associates the given 'addresses' with 'hostname'. The association will expire after a
     * certain length of time.
     */
    public void put(String hostname, int netId, InetAddress[] addresses) {
        cache.put(new AddressCacheKey(hostname, netId), new AddressCacheEntry(addresses));
    }

    /**
     * Records that 'hostname' is known not to have any associated addresses. (I.e. insert a
     * negative cache entry.)
     */
    public void putUnknownHost(String hostname, int netId, String detailMessage) {
        cache.put(new AddressCacheKey(hostname, netId), new AddressCacheEntry(detailMessage));
    }
}
