553N/A * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 0N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 553N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A * or visit www.oracle.com if you need additional information or have any 0N/A * Solaris implementation of WatchService based on file events notification 0N/A * typedef struct port_event { 0N/A * int portev_events; 0N/A * ushort_t portev_source; 0N/A * ushort_t portev_pad; 0N/A * uintptr_t portev_object; 0N/A * void *portev_user; 0N/A * typedef struct file_obj { 0N/A * timestruc_t fo_atime; 0N/A * timestruc_t fo_mtime; 0N/A * timestruc_t fo_ctime; 0N/A * uintptr_t fo_pad[3]; 0N/A // user-watchable events // background thread to read change events * WatchKey implementation // pointer to native file_obj object // events (may be changed). set to null when watch key is invalid // map of entries in directory; created lazily; accessed only by * Background thread to read from port // maximum number of events to read per call to port_getn // events that map to ENTRY_DELETE // events that tell us not to re-associate the object // address of event buffers (used to receive events with port_getn) // maps file key (dev/inode) to WatchKey // maps file_obj object to Node // write to port to wakeup polling thread // no modifiers supported at this time // check file is directory // return existing watch key after updating events if already // create watch key and insert it into maps // register all entries in directory // release resources for entries in directory // release resources for directory // and finally invalidate the key // release all native resources * Poller main loop. Blocks on port_getn waiting for events and then for (
int i=
0; i<n; i++) {
* Process a single port_event * Returns true if poller thread is requested to shutdown. // user event is trigger to process pending requests // process any pending requests // lookup object to get Node // 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; // If node is EntryNode then event relates to entry in directory // If node is a SolarisWatchKey (DirectoryNode) then event relates // to a watched directory. // need to re-associate to get further events // object is not re-registered so release resources. If // object is a watched directory then signal key // if watch key then signal it // if entry then remove it from parent * Process directory events. If directory is modified then re-scan * directory to register any new entries * Process events for entries in registered directories. Returns {@code * true} if events are ignored because the watch key has been cancelled. // key has been cancelled so ignore event // Due to 6636438/6636412 we may get a remove event for cases // 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. * 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. // if the ENTRY_MODIFY event is not enabled then we don't need // modification events for entries in the directory // skip entry if already registered // send ENTRY_CREATE if enabled // can't register so ignore for now. // tell the parent about it // error during iteration which we ignore for now * Update watch key's events. Where the ENTRY_MODIFY changes then we * need to update the events of registered children. // update events, rembering if ENTRY_MODIFY was previously // check if ENTRY_MODIFY has changed // if changed then update events of children * Calls port_associate to register the given path. * Returns pointer to fileobj structure that is allocated for // allocate memory for the path (file_obj->fo_name field) // allocate memory for filedatanode structure - this is the object // associate the object with the port "with the port has been reached");
* Frees all resources for an file_obj object; optionally remove * A node with native (file_obj) resources private static interface Node {
* A directory node with a map of the entries in the directory * An implementation of a node that is an entry in a directory. private static native void init();