/*
 * Copyright (c) 2008, 2009, 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.nio.fs;

import java.nio.file.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.io.IOException;
import sun.misc.Unsafe;

import static sun.nio.fs.UnixConstants.*;

/**
 * Solaris implementation of WatchService based on file events notification
 * facility.
 */

class SolarisWatchService
    extends AbstractWatchService
{
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static int addressSize = unsafe.addressSize();

    private static int dependsArch(int value32, int value64) {
        return (addressSize == 4) ? value32 : value64;
    }

    /*
     * typedef struct port_event {
     *     int             portev_events;
     *     ushort_t        portev_source;
     *     ushort_t        portev_pad;
     *     uintptr_t       portev_object;
     *     void            *portev_user;
     * } port_event_t;
     */
    private static final int SIZEOF_PORT_EVENT  = dependsArch(16, 24);
    private static final int OFFSETOF_EVENTS    = 0;
    private static final int OFFSETOF_SOURCE    = 4;
    private static final int OFFSETOF_OBJECT    = 8;

    /*
     * typedef struct file_obj {
     *     timestruc_t     fo_atime;
     *     timestruc_t     fo_mtime;
     *     timestruc_t     fo_ctime;
     *     uintptr_t       fo_pad[3];
     *     char            *fo_name;
     * } file_obj_t;
     */
    private static final int SIZEOF_FILEOBJ    = dependsArch(40, 80);
    private static final int OFFSET_FO_NAME    = dependsArch(36, 72);

    // port sources
    private static final short PORT_SOURCE_USER     = 3;
    private static final short PORT_SOURCE_FILE     = 7;

    // user-watchable events
    private static final int FILE_MODIFIED      = 0x00000002;
    private static final int FILE_ATTRIB        = 0x00000004;
    private static final int FILE_NOFOLLOW      = 0x10000000;

    // exception events
    private static final int FILE_DELETE        = 0x00000010;
    private static final int FILE_RENAME_TO     = 0x00000020;
    private static final int FILE_RENAME_FROM   = 0x00000040;
    private static final int UNMOUNTED          = 0x20000000;
    private static final int MOUNTEDOVER        = 0x40000000;

    // background thread to read change events
    private final Poller poller;

    SolarisWatchService(UnixFileSystem fs) throws IOException {
        int port = -1;
        try {
            port = portCreate();
        } catch (UnixException x) {
            throw new IOException(x.errorString());
        }

        this.poller = new Poller(fs, this, port);
        this.poller.start();
    }

    @Override
    WatchKey register(Path dir,
                      WatchEvent.Kind<?>[] events,
                      WatchEvent.Modifier... modifiers)
         throws IOException
    {
        // delegate to poller
        return poller.register(dir, events, modifiers);
    }

    @Override
    void implClose() throws IOException {
        // delegate to poller
        poller.close();
    }

    /**
     * WatchKey implementation
     */
    private class SolarisWatchKey extends AbstractWatchKey
        implements DirectoryNode
    {
        private final UnixPath dir;
        private final UnixFileKey fileKey;

        // pointer to native file_obj object
        private final long object;

        // events (may be changed). set to null when watch key is invalid
        private volatile Set<? extends WatchEvent.Kind<?>> events;

        // map of entries in directory; created lazily; accessed only by
        // poller thread.
        private Map<Path,EntryNode> children;

        SolarisWatchKey(SolarisWatchService watcher,
                        UnixPath dir,
                        UnixFileKey fileKey,
                        long object,
                        Set<? extends WatchEvent.Kind<?>> events)
        {
            super(watcher);
            this.dir = dir;
            this.fileKey = fileKey;
            this.object = object;
            this.events = events;
        }

        UnixPath getFileRef() {
            return dir;
        }

        UnixFileKey getFileKey() {
            return fileKey;
        }

        @Override
        public long object() {
            return object;
        }

        void invalidate() {
            events = null;
        }

        Set<? extends WatchEvent.Kind<?>> events() {
            return events;
        }

        void setEvents(Set<? extends WatchEvent.Kind<?>> events) {
            this.events = events;
        }

        @Override
        public boolean isValid() {
            return events != null;
        }

        @Override
        public void cancel() {
            if (isValid()) {
                // delegate to poller
                poller.cancel(this);
            }
        }

        @Override
        public void addChild(Path name, EntryNode node) {
            if (children == null)
                children = new HashMap<Path,EntryNode>();
            children.put(name, node);
        }

        @Override
        public void removeChild(Path name) {
            children.remove(name);
        }

        @Override
        public EntryNode getChild(Path name) {
            if (children != null)
                return children.get(name);
            return null;
        }
    }

    /**
     * Background thread to read from port
     */
    private class Poller extends AbstractPoller {

        // maximum number of events to read per call to port_getn
        private static final int MAX_EVENT_COUNT            = 128;

        // events that map to ENTRY_DELETE
        private static final int FILE_REMOVED =
            (FILE_DELETE|FILE_RENAME_TO|FILE_RENAME_FROM);

        // events that tell us not to re-associate the object
        private static final int FILE_EXCEPTION =
            (FILE_REMOVED|UNMOUNTED|MOUNTEDOVER);

        // address of event buffers (used to receive events with port_getn)
        private final long bufferAddress;

        private final SolarisWatchService watcher;

        // the I/O port
        private final int port;

        // maps file key (dev/inode) to WatchKey
        private final Map<UnixFileKey,SolarisWatchKey> fileKey2WatchKey;

        // maps file_obj object to Node
        private final Map<Long,Node> object2Node;

        /**
         * Create a new instance
         */
        Poller(UnixFileSystem fs, SolarisWatchService watcher, int port) {
            this.watcher = watcher;
            this.port = port;
            this.bufferAddress =
                unsafe.allocateMemory(SIZEOF_PORT_EVENT * MAX_EVENT_COUNT);
            this.fileKey2WatchKey = new HashMap<UnixFileKey,SolarisWatchKey>();
            this.object2Node = new HashMap<Long,Node>();
        }

        @Override
        void wakeup() throws IOException {
            // write to port to wakeup polling thread
            try {
                portSend(port, 0);
            } catch (UnixException x) {
                throw new IOException(x.errorString());
            }
        }

        @Override
        Object implRegister(Path obj,
                            Set<? extends WatchEvent.Kind<?>> events,
                            WatchEvent.Modifier... modifiers)
        {
            // no modifiers supported at this time
            if (modifiers.length > 0) {
                for (WatchEvent.Modifier modifier: modifiers) {
                    if (modifier == null)
                        return new NullPointerException();
                    if (modifier instanceof com.sun.nio.file.SensitivityWatchEventModifier)
                        continue; // ignore
                    return new UnsupportedOperationException("Modifier not supported");
                }
            }

            UnixPath dir = (UnixPath)obj;

            // check file is directory
            UnixFileAttributes attrs = null;
            try {
                attrs = UnixFileAttributes.get(dir, true);
            } catch (UnixException x) {
                return x.asIOException(dir);
            }
            if (!attrs.isDirectory()) {
                return new NotDirectoryException(dir.getPathForExecptionMessage());
            }

            // return existing watch key after updating events if already
            // registered
            UnixFileKey fileKey = attrs.fileKey();
            SolarisWatchKey watchKey = fileKey2WatchKey.get(fileKey);
            if (watchKey != null) {
                updateEvents(watchKey, events);
                return watchKey;
            }

            // register directory
            long object = 0L;
            try {
                object = registerImpl(dir, (FILE_MODIFIED | FILE_ATTRIB));
            } catch (UnixException x) {
                return x.asIOException(dir);
            }

            // create watch key and insert it into maps
            watchKey = new SolarisWatchKey(watcher, dir, fileKey, object, events);
            object2Node.put(object, watchKey);
            fileKey2WatchKey.put(fileKey, watchKey);

            // register all entries in directory
            registerChildren(dir, watchKey, false);

            return watchKey;
        }

        // cancel single key
        @Override
        void implCancelKey(WatchKey obj) {
           SolarisWatchKey key = (SolarisWatchKey)obj;
           if (key.isValid()) {
               fileKey2WatchKey.remove(key.getFileKey());

               // release resources for entries in directory
               if (key.children != null) {
                   for (Map.Entry<Path,EntryNode> entry: key.children.entrySet()) {
                       EntryNode node = entry.getValue();
                       long object = node.object();
                       object2Node.remove(object);
                       releaseObject(object, true);
                   }
               }

               // release resources for directory
               long object = key.object();
               object2Node.remove(object);
               releaseObject(object, true);

               // and finally invalidate the key
               key.invalidate();
           }
        }

        // close watch service
        @Override
        void implCloseAll() {
            // release all native resources
            for (Long object: object2Node.keySet()) {
                releaseObject(object, true);
            }

            // invalidate all keys
            for (Map.Entry<UnixFileKey,SolarisWatchKey> entry: fileKey2WatchKey.entrySet()) {
                entry.getValue().invalidate();
            }

            // clean-up
            object2Node.clear();
            fileKey2WatchKey.clear();

            // free global resources
            unsafe.freeMemory(bufferAddress);
            UnixNativeDispatcher.close(port);
        }

        /**
         * Poller main loop. Blocks on port_getn waiting for events and then
         * processes them.
         */
        @Override
        public void run() {
            try {
                for (;;) {
                    int n = portGetn(port, bufferAddress, MAX_EVENT_COUNT);
                    assert n > 0;

                    long address = bufferAddress;
                    for (int i=0; i<n; i++) {
                        boolean shutdown = processEvent(address);
                        if (shutdown)
                            return;
                        address += SIZEOF_PORT_EVENT;
                    }
                }
            } catch (UnixException x) {
                x.printStackTrace();
            }
        }

        /**
         * Process a single port_event
         *
         * Returns true if poller thread is requested to shutdown.
         */
        boolean processEvent(long address) {
            // pe->portev_source
            short source = unsafe.getShort(address + OFFSETOF_SOURCE);
            // pe->portev_object
            long object = unsafe.getAddress(address + OFFSETOF_OBJECT);
            // pe->portev_events
            int events = unsafe.getInt(address + OFFSETOF_EVENTS);

            // user event is trigger to process pending requests
            if (source != PORT_SOURCE_FILE) {
                if (source == PORT_SOURCE_USER) {
                    // process any pending requests
                    boolean shutdown = processRequests();
                    if (shutdown)
                        return true;
                }
                return false;
            }

            // lookup object to get Node
            Node node = object2Node.get(object);
            if (node == null) {
                // should not happen
                return false;
            }

            // As a workaround for 6642290 and 6636438/6636412 we don't use
            // FILE_EXCEPTION events to tell use not to register the file.
            // boolean reregister = (events & FILE_EXCEPTION) == 0;
            boolean reregister = true;

            // If node is EntryNode then event relates to entry in directory
            // If node is a SolarisWatchKey (DirectoryNode) then event relates
            // to a watched directory.
            boolean isDirectory = (node instanceof SolarisWatchKey);
            if (isDirectory) {
                processDirectoryEvents((SolarisWatchKey)node, events);
            } else {
                boolean ignore = processEntryEvents((EntryNode)node, events);
                if (ignore)
                    reregister = false;
            }

            // need to re-associate to get further events
            if (reregister) {
                try {
                    events = FILE_MODIFIED | FILE_ATTRIB;
                    if (!isDirectory) events |= FILE_NOFOLLOW;
                    portAssociate(port,
                                  PORT_SOURCE_FILE,
                                  object,
                                  events);
                } catch (UnixException x) {
                    // unable to re-register
                    reregister = false;
                }
            }

            // object is not re-registered so release resources. If
            // object is a watched directory then signal key
            if (!reregister) {
                // release resources
                object2Node.remove(object);
                releaseObject(object, false);

                // if watch key then signal it
                if (isDirectory) {
                    SolarisWatchKey key = (SolarisWatchKey)node;
                    fileKey2WatchKey.remove( key.getFileKey() );
                    key.invalidate();
                    key.signal();
                } else {
                    // if entry then remove it from parent
                    EntryNode entry = (EntryNode)node;
                    SolarisWatchKey key = (SolarisWatchKey)entry.parent();
                    key.removeChild(entry.name());
                }
            }

            return false;
        }

        /**
         * Process directory events. If directory is modified then re-scan
         * directory to register any new entries
         */
        void processDirectoryEvents(SolarisWatchKey key, int mask) {
            if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) {
                registerChildren(key.getFileRef(), key,
                    key.events().contains(StandardWatchEventKind.ENTRY_CREATE));
            }
        }

        /**
         * Process events for entries in registered directories. Returns {@code
         * true} if events are ignored because the watch key has been cancelled.
         */
        boolean processEntryEvents(EntryNode node, int mask) {
            SolarisWatchKey key = (SolarisWatchKey)node.parent();
            Set<? extends WatchEvent.Kind<?>> events = key.events();
            if (events == null) {
                // key has been cancelled so ignore event
                return true;
            }

            // entry modified
            if (((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) &&
                events.contains(StandardWatchEventKind.ENTRY_MODIFY))
            {
                key.signalEvent(StandardWatchEventKind.ENTRY_MODIFY, node.name());
            }

            // entry removed
            if (((mask & (FILE_REMOVED)) != 0) &&
                events.contains(StandardWatchEventKind.ENTRY_DELETE))
            {
                // Due to 6636438/6636412 we may get a remove event for cases
                // where a rmdir/unlink/rename is attempted but fails. Until
                // this issue is resolved we re-lstat the file to check if it
                // exists. If it exists then we ignore the event. To keep the
                // workaround simple we don't check the st_ino so it isn't
                // effective when the file is replaced.
                boolean removed = true;
                try {
                    UnixFileAttributes
                        .get(key.getFileRef().resolve(node.name()), false);
                    removed = false;
                } catch (UnixException x) { }

                if (removed)
                    key.signalEvent(StandardWatchEventKind.ENTRY_DELETE, node.name());
            }
            return false;
        }

        /**
         * Registers all entries in the given directory
         *
         * The {@code sendEvents} parameter indicates if ENTRY_CREATE events
         * should be queued when new entries are found. When initially
         * registering a directory then will always be false. When re-scanning
         * a directory then it depends on if the event is enabled or not.
         */
        void registerChildren(UnixPath dir,
                              SolarisWatchKey parent,
                              boolean sendEvents)
        {
            // if the ENTRY_MODIFY event is not enabled then we don't need
            // modification events for entries in the directory
            int events = FILE_NOFOLLOW;
            if (parent.events().contains(StandardWatchEventKind.ENTRY_MODIFY))
                events |= (FILE_MODIFIED | FILE_ATTRIB);

            DirectoryStream<Path> stream = null;
            try {
                stream = dir.newDirectoryStream();
            } catch (IOException x) {
                // nothing we can do
                return;
            }
            try {
                for (Path entry: stream) {
                    Path name = entry.getName();

                    // skip entry if already registered
                    if (parent.getChild(name) != null)
                        continue;

                    // send ENTRY_CREATE if enabled
                    if (sendEvents) {
                        parent.signalEvent(StandardWatchEventKind.ENTRY_CREATE, name);
                    }

                    // register it
                    long object = 0L;
                    try {
                        object = registerImpl((UnixPath)entry, events);
                    } catch (UnixException x) {
                        // can't register so ignore for now.
                        continue;
                    }

                    // create node
                    EntryNode node = new EntryNode(object, entry.getName(), parent);
                    // tell the parent about it
                    parent.addChild(entry.getName(), node);
                    object2Node.put(object, node);
                }
            } catch (ConcurrentModificationException x) {
                // error during iteration which we ignore for now
            } finally {
                try {
                    stream.close();
                } catch (IOException x) { }
            }
        }

        /**
         * Update watch key's events. Where the ENTRY_MODIFY changes then we
         * need to update the events of registered children.
         */
        void updateEvents(SolarisWatchKey key, Set<? extends WatchEvent.Kind<?>> events) {
            // update events, rembering if ENTRY_MODIFY was previously
            // enabled or disabled.
            boolean wasModifyEnabled = key.events()
                .contains(StandardWatchEventKind.ENTRY_MODIFY);
            key.setEvents(events);

            // check if ENTRY_MODIFY has changed
            boolean isModifyEnabled = events
                .contains(StandardWatchEventKind.ENTRY_MODIFY);
            if (wasModifyEnabled == isModifyEnabled) {
                return;
            }

            // if changed then update events of children
            if (key.children != null) {
                int ev = FILE_NOFOLLOW;
                if (isModifyEnabled)
                    ev |= (FILE_MODIFIED | FILE_ATTRIB);

                for (Map.Entry<Path,EntryNode> entry: key.children.entrySet()) {
                    long object = entry.getValue().object();
                    try {
                        portAssociate(port,
                                      PORT_SOURCE_FILE,
                                      object,
                                      ev);
                    } catch (UnixException x) {
                        // nothing we can do.
                    }
                }
            }
        }

        /**
         * Calls port_associate to register the given path.
         * Returns pointer to fileobj structure that is allocated for
         * the registration.
         */
        long registerImpl(UnixPath dir, int events)
            throws UnixException
        {
            // allocate memory for the path (file_obj->fo_name field)
            byte[] path = dir.getByteArrayForSysCalls();
            int len = path.length;
            long name = unsafe.allocateMemory(len+1);
            unsafe.copyMemory(path, Unsafe.ARRAY_BYTE_BASE_OFFSET, null,
                name, (long)len);
            unsafe.putByte(name + len, (byte)0);

            // allocate memory for filedatanode structure - this is the object
            // to port_associate
            long object = unsafe.allocateMemory(SIZEOF_FILEOBJ);
            unsafe.setMemory(null, object, SIZEOF_FILEOBJ, (byte)0);
            unsafe.putAddress(object + OFFSET_FO_NAME, name);

            // associate the object with the port
            try {
                portAssociate(port,
                              PORT_SOURCE_FILE,
                              object,
                              events);
            } catch (UnixException x) {
                // debugging
                if (x.errno() == EAGAIN) {
                    System.err.println("The maximum number of objects associated "+
                        "with the port has been reached");
                }

                unsafe.freeMemory(name);
                unsafe.freeMemory(object);
                throw x;
            }
            return object;
        }

        /**
         * Frees all resources for an file_obj object; optionally remove
         * association from port
         */
        void releaseObject(long object, boolean dissociate) {
            // remove association
            if (dissociate) {
                try {
                    portDissociate(port, PORT_SOURCE_FILE, object);
                } catch (UnixException x) {
                    // ignore
                }
            }

            // free native memory
            long name = unsafe.getAddress(object + OFFSET_FO_NAME);
            unsafe.freeMemory(name);
            unsafe.freeMemory(object);
        }
    }

    /**
     * A node with native (file_obj) resources
     */
    private static interface Node {
        long object();
    }

    /**
     * A directory node with a map of the entries in the directory
     */
    private static interface DirectoryNode extends Node {
        void addChild(Path name, EntryNode node);
        void removeChild(Path name);
        EntryNode getChild(Path name);
    }

    /**
     * An implementation of a node that is an entry in a directory.
     */
    private static class EntryNode implements Node {
        private final long object;
        private final Path name;
        private final DirectoryNode parent;

        EntryNode(long object, Path name, DirectoryNode parent) {
            this.object = object;
            this.name = name;
            this.parent = parent;
        }

        @Override
        public long object() {
            return object;
        }

        Path name() {
            return name;
        }

        DirectoryNode parent() {
            return parent;
        }
    }

    // -- native methods --

    private static native void init();

    private static native int portCreate() throws UnixException;

    private static native void portAssociate(int port, int source, long object, int events)
        throws UnixException;

    private static native void portDissociate(int port, int source, long object)
        throws UnixException;

    private static native void portSend(int port, int events)
        throws UnixException;

    private static native int portGetn(int port, long address, int max)
        throws UnixException;

    static {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                System.loadLibrary("nio");
                return null;
        }});
        init();
    }
}
