/*
 * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package sun.rmi.transport;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.dgc.DGC;
import java.rmi.dgc.Lease;
import java.rmi.dgc.VMID;
import java.rmi.server.LogStream;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteServer;
import java.rmi.server.ServerNotActiveException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import sun.rmi.runtime.Log;
import sun.rmi.runtime.RuntimeUtil;
import sun.rmi.server.UnicastRef;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.Util;
import sun.security.action.GetLongAction;
import sun.security.action.GetPropertyAction;

/**
 * This class implements the guts of the server-side distributed GC
 * algorithm
 *
 * @author Ann Wollrath
 */
final class DGCImpl implements DGC {

    /* dgc system log */
    static final Log dgcLog = Log.getLog("sun.rmi.dgc", "dgc",
        LogStream.parseLevel(AccessController.doPrivileged(
            new GetPropertyAction("sun.rmi.dgc.logLevel"))));

    /** lease duration to grant to clients */
    private static final long leaseValue =              // default 10 minutes
        AccessController.doPrivileged(
            new GetLongAction("java.rmi.dgc.leaseValue", 600000));

    /** lease check interval; default is half of lease grant duration */
    private static final long leaseCheckInterval =
        AccessController.doPrivileged(
            new GetLongAction("sun.rmi.dgc.checkInterval", leaseValue / 2));

    /** thread pool for scheduling delayed tasks */
    private static final ScheduledExecutorService scheduler =
        AccessController.doPrivileged(
            new RuntimeUtil.GetInstanceAction()).getScheduler();

    /** remote implementation of DGC interface for this VM */
    private static DGCImpl dgc;
    /** table that maps VMID to LeaseInfo */
    private Map<VMID,LeaseInfo> leaseTable = new HashMap<VMID,LeaseInfo>();
    /** checks for lease expiration */
    private Future<?> checker = null;

    /**
     * Return the remote implementation of the DGC interface for
     * this VM.
     */
    static DGCImpl getDGCImpl() {
        return dgc;
    }

    /**
     * Construct a new server-side remote object collector at
     * a particular port. Disallow construction from outside.
     */
    private DGCImpl() {}

    /**
     * The dirty call adds the VMID "vmid" to the set of clients
     * that hold references to the object associated with the ObjID
     * id.  The long "sequenceNum" is used to detect late dirty calls.  If
     * the VMID "vmid" is null, a VMID will be generated on the
     * server (for use by the client in subsequent calls) and
     * returned.
     *
     * The client must call the "dirty" method to renew the lease
     * before the "lease" time expires or all references to remote
     * objects in this VM that the client holds are considered
     * "unreferenced".
     */
    public Lease dirty(ObjID[] ids, long sequenceNum, Lease lease) {
        VMID vmid = lease.getVMID();
        /*
         * The server specifies the lease value; the client has
         * no say in the matter.
         */
        long duration = leaseValue;

        if (dgcLog.isLoggable(Log.VERBOSE)) {
            dgcLog.log(Log.VERBOSE, "vmid = " + vmid);
        }

        // create a VMID if one wasn't supplied
        if (vmid == null) {
            vmid = new VMID();

            if (dgcLog.isLoggable(Log.BRIEF)) {
                String clientHost;
                try {
                    clientHost = RemoteServer.getClientHost();
                } catch (ServerNotActiveException e) {
                    clientHost = "<unknown host>";
                }
                dgcLog.log(Log.BRIEF, " assigning vmid " + vmid +
                           " to client " + clientHost);
            }
        }

        lease = new Lease(vmid, duration);
        // record lease information
        synchronized (leaseTable) {
            LeaseInfo info = leaseTable.get(vmid);
            if (info == null) {
                leaseTable.put(vmid, new LeaseInfo(vmid, duration));
                if (checker == null) {
                    checker = scheduler.scheduleWithFixedDelay(
                        new Runnable() {
                            public void run() {
                                checkLeases();
                            }
                        },
                        leaseCheckInterval,
                        leaseCheckInterval, TimeUnit.MILLISECONDS);
                }
            } else {
                info.renew(duration);
            }
        }

        for (ObjID id : ids) {
            if (dgcLog.isLoggable(Log.VERBOSE)) {
                dgcLog.log(Log.VERBOSE, "id = " + id +
                           ", vmid = " + vmid + ", duration = " + duration);
            }

            ObjectTable.referenced(id, sequenceNum, vmid);
        }

        // return the VMID used
        return lease;
    }

    /**
     * The clean call removes the VMID from the set of clients
     * that hold references to the object associated with the LiveRef
     * ref.  The sequence number is used to detect late clean calls.  If the
     * argument "strong" is true, then the clean call is a result of a
     * failed "dirty" call, thus the sequence number for the VMID needs
     * to be remembered until the client goes away.
     */
    public void clean(ObjID[] ids, long sequenceNum, VMID vmid, boolean strong)
    {
        for (ObjID id : ids) {
            if (dgcLog.isLoggable(Log.VERBOSE)) {
                dgcLog.log(Log.VERBOSE, "id = " + id +
                    ", vmid = " + vmid + ", strong = " + strong);
            }

            ObjectTable.unreferenced(id, sequenceNum, vmid, strong);
        }
    }

    /**
     * Register interest in receiving a callback when this VMID
     * becomes inaccessible.
     */
    void registerTarget(VMID vmid, Target target) {
        synchronized (leaseTable) {
            LeaseInfo info = leaseTable.get(vmid);
            if (info == null) {
                target.vmidDead(vmid);
            } else {
                info.notifySet.add(target);
            }
        }
    }

    /**
     * Remove notification request.
     */
    void unregisterTarget(VMID vmid, Target target) {
        synchronized (leaseTable) {
            LeaseInfo info = leaseTable.get(vmid);
            if (info != null) {
                info.notifySet.remove(target);
            }
        }
    }

    /**
     * Check if leases have expired.  If a lease has expired, remove
     * it from the table and notify all interested parties that the
     * VMID is essentially "dead".
     *
     * @return if true, there are leases outstanding; otherwise leases
     * no longer need to be checked
     */
    private void checkLeases() {
        long time = System.currentTimeMillis();

        /* List of vmids that need to be removed from the leaseTable */
        List<LeaseInfo> toUnregister = new ArrayList<LeaseInfo>();

        /* Build a list of leaseInfo objects that need to have
         * targets removed from their notifySet.  Remove expired
         * leases from leaseTable.
         */
        synchronized (leaseTable) {
            Iterator<LeaseInfo> iter = leaseTable.values().iterator();
            while (iter.hasNext()) {
                LeaseInfo info = iter.next();
                if (info.expired(time)) {
                    toUnregister.add(info);
                    iter.remove();
                }
            }

            if (leaseTable.isEmpty()) {
                checker.cancel(false);
                checker = null;
            }
        }

        /* Notify and unegister targets without holding the lock on
         * the leaseTable so we avoid deadlock.
         */
        for (LeaseInfo info : toUnregister) {
            for (Target target : info.notifySet) {
                target.vmidDead(info.vmid);
            }
        }
    }

    static {
        /*
         * "Export" the singleton DGCImpl in a context isolated from
         * the arbitrary current thread context.
         */
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                ClassLoader savedCcl =
                    Thread.currentThread().getContextClassLoader();
                try {
                    Thread.currentThread().setContextClassLoader(
                        ClassLoader.getSystemClassLoader());

                    /*
                     * Put remote collector object in table by hand to prevent
                     * listen on port.  (UnicastServerRef.exportObject would
                     * cause transport to listen.)
                     */
                    try {
                        dgc = new DGCImpl();
                        ObjID dgcID = new ObjID(ObjID.DGC_ID);
                        LiveRef ref = new LiveRef(dgcID, 0);
                        UnicastServerRef disp = new UnicastServerRef(ref);
                        Remote stub =
                            Util.createProxy(DGCImpl.class,
                                             new UnicastRef(ref), true);
                        disp.setSkeleton(dgc);
                        Target target =
                            new Target(dgc, disp, stub, dgcID, true);
                        ObjectTable.putTarget(target);
                    } catch (RemoteException e) {
                        throw new Error(
                            "exception initializing server-side DGC", e);
                    }
                } finally {
                    Thread.currentThread().setContextClassLoader(savedCcl);
                }
                return null;
            }
        });
    }

    private static class LeaseInfo {
        VMID vmid;
        long expiration;
        Set<Target> notifySet = new HashSet<Target>();

        LeaseInfo(VMID vmid, long lease) {
            this.vmid = vmid;
            expiration = System.currentTimeMillis() + lease;
        }

        synchronized void renew(long lease) {
            long newExpiration = System.currentTimeMillis() + lease;
            if (newExpiration > expiration)
                expiration = newExpiration;
        }

        boolean expired(long time) {
            if (expiration < time) {
                if (dgcLog.isLoggable(Log.BRIEF)) {
                    dgcLog.log(Log.BRIEF, vmid.toString());
                }
                return true;
            } else {
                return false;
            }
        }
    }
}
