This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 197966
Collapse All | Expand All

(-)a/masterfs/src/org/netbeans/modules/masterfs/watcher/LinuxNotifier.java (-37 / +108 lines)
Lines 42-51 Link Here
42
import com.sun.jna.Library;
42
import com.sun.jna.Library;
43
import com.sun.jna.Native;
43
import com.sun.jna.Native;
44
import com.sun.jna.NativeLibrary;
44
import com.sun.jna.NativeLibrary;
45
import com.sun.jna.NativeLong;
46
import com.sun.jna.Structure;
45
import java.io.IOException;
47
import java.io.IOException;
46
import java.nio.ByteBuffer;
48
import java.nio.ByteBuffer;
47
import java.nio.ByteOrder;
49
import java.nio.ByteOrder;
50
import java.util.ArrayList;
51
import java.util.Arrays;
48
import java.util.HashMap;
52
import java.util.HashMap;
53
import java.util.List;
49
import java.util.Map;
54
import java.util.Map;
50
import java.util.logging.Level;
55
import java.util.logging.Level;
51
import java.util.logging.Logger;
56
import java.util.logging.Logger;
Lines 57-70 Link Here
57
 */
62
 */
58
final class LinuxNotifier extends Notifier<LinuxNotifier.LKey> {
63
final class LinuxNotifier extends Notifier<LinuxNotifier.LKey> {
59
    private static final Logger LOG = Logger.getLogger(LinuxNotifier.class.getName());
64
    private static final Logger LOG = Logger.getLogger(LinuxNotifier.class.getName());
65
66
    public static class PollFd extends Structure {
67
        public int fd;
68
        public short events;
69
        public short revents;
70
        
71
        public static final short POLLIN = 0x01; // something to read
72
        
73
        public PollFd(int fd) {
74
            this.fd = fd;
75
            events = POLLIN;
76
        }
77
        
78
        public boolean hasData() {
79
            return (revents & POLLIN) != 0;
80
        }
81
82
        @Override
83
        public String toString() {
84
            return "PollFd[" + fd + "]";
85
        }
86
        
87
    }
88
    public static class TimeVal extends Structure {
89
        public NativeLong seconds;
90
        public NativeLong nano;
91
    }
60
    
92
    
61
    private static interface InotifyImpl extends Library {
93
    private static interface InotifyImpl extends Library {
62
	public int inotify_init();
94
        public int inotify_init();
63
	public int inotify_init1(int flags);
95
        public int inotify_init1(int flags);
64
	public int close(int fd);
96
        public int close(int fd);
65
    public int read(int fd, ByteBuffer buff, int count);
97
        public int poll(PollFd[] fds, NativeLong numberOfFDs, int timeout);
66
	public int inotify_add_watch(int fd, String pathname, int mask);
98
        public int read(int fd, ByteBuffer buff, int count);
67
	public int inotify_rm_watch(int fd, int wd);
99
        public int inotify_add_watch(int fd, String pathname, int mask);
100
        public int inotify_rm_watch(int fd, int wd);
101
        
68
102
69
        public static final int O_CLOEXEC = 02000000; //0x80000
103
        public static final int O_CLOEXEC = 02000000; //0x80000
70
104
Lines 90-96 Link Here
90
    }
124
    }
91
125
92
    final InotifyImpl IMPL;
126
    final InotifyImpl IMPL;
93
    int fd;
127
    private PollFd[] polls;
94
    private ByteBuffer buff = ByteBuffer.allocateDirect(4096);
128
    private ByteBuffer buff = ByteBuffer.allocateDirect(4096);
95
129
96
    // An array would serve nearly as well
130
    // An array would serve nearly as well
Lines 100-117 Link Here
100
         IMPL = (InotifyImpl) Native.loadLibrary("c", InotifyImpl.class);
134
         IMPL = (InotifyImpl) Native.loadLibrary("c", InotifyImpl.class);
101
         buff.position(buff.capacity()); // make the buffer empty
135
         buff.position(buff.capacity()); // make the buffer empty
102
         buff.order(ByteOrder.nativeOrder());
136
         buff.order(ByteOrder.nativeOrder());
103
         fd = IMPL.inotify_init1(InotifyImpl.O_CLOEXEC);
137
         polls = new PollFd[] { new PollFd(allocFD()) };
104
         if (fd < 0) {
138
    }
105
             LOG.log(
139
106
                 Level.INFO, "Linux kernel {0} returned {1} from inotify_init1",
140
    private int allocFD() throws IllegalStateException {
107
                 new Object[] { System.getProperty("os.version"), fd }
141
        int fd = IMPL.inotify_init1(InotifyImpl.O_CLOEXEC);
108
             );
142
        if (fd < 0) {
109
             fd = IMPL.inotify_init();
143
            LOG.log(
110
             LOG.log(Level.INFO, "Trying inotify_init: {0}", fd);
144
                Level.INFO, "Linux kernel {0} returned {1} from inotify_init1",
111
         }
145
                new Object[] { System.getProperty("os.version"), fd }
112
         if (fd < 0) {
146
            );
113
             throw new IllegalStateException("inotify_init failed: " + fd);
147
            fd = IMPL.inotify_init();
114
         }
148
            LOG.log(Level.INFO, "Trying inotify_init: {0}", fd);
149
        }
150
        if (fd < 0) {
151
            throw new IllegalStateException("inotify_init failed: " + fd);
152
        }
153
        return fd;
115
    }
154
    }
116
155
117
    private String getString(int maxLen) {
156
    private String getString(int maxLen) {
Lines 133-140 Link Here
133
         */
172
         */
134
        while (buff.remaining() < 16 || buff.remaining() < 16 + buff.getInt(buff.position() + 12)) {
173
        while (buff.remaining() < 16 || buff.remaining() < 16 + buff.getInt(buff.position() + 12)) {
135
            buff.compact();
174
            buff.compact();
136
            int len = IMPL.read(fd, buff, buff.remaining());
175
            LOG.log(Level.FINEST, "before select from {0}", polls.length);
137
176
            IMPL.poll(polls, new NativeLong(1), -1);
177
            LOG.log(Level.FINEST, "before select from {0}", polls.length);
178
            int len = -1;
179
            for (PollFd fd : polls) {
180
                LOG.log(Level.FINEST, "{0}  has data {1}", new Object[]{fd, fd.hasData()});
181
                if (fd.hasData()) {
182
                    len = IMPL.read(fd.fd, buff, buff.remaining());
183
                    break;
184
                }
185
            }
138
            if (len <= 0) {
186
            if (len <= 0) {
139
                // lazily get a thread local errno
187
                // lazily get a thread local errno
140
                int errno = NativeLibrary.getInstance("c").getFunction("errno").getInt(0);
188
                int errno = NativeLibrary.getInstance("c").getFunction("errno").getInt(0);
Lines 166-177 Link Here
166
214
167
215
168
    static class LKey {
216
    static class LKey {
169
        int id;
217
        final int id;
170
        String path;
218
        final String path;
219
        final PollFd from;
171
220
172
        public LKey(int id, String path) {
221
        public LKey(int id, String path, PollFd from) {
173
            this.id = id;
222
            this.id = id;
174
            this.path = path;
223
            this.path = path;
224
            this.from = from;
175
        }
225
        }
176
226
177
        @Override
227
        @Override
Lines 181-202 Link Here
181
    }
231
    }
182
232
183
    @Override public LKey addWatch(String path) throws IOException {
233
    @Override public LKey addWatch(String path) throws IOException {
184
        // what if the file doesn't exist?
234
        int id = -1;
185
        int id = IMPL.inotify_add_watch(fd, path,
235
        PollFd from = null;
186
                    InotifyImpl.IN_CREATE | InotifyImpl.IN_MOVED_TO |
236
        List<PollFd> arr = Arrays.asList(polls);
187
                    InotifyImpl.IN_DELETE | InotifyImpl.IN_MOVED_FROM |
237
        OK: for (int twice = 0; twice < 2; twice++) {
188
                    InotifyImpl.IN_MODIFY | InotifyImpl.IN_ATTRIB);
238
            // what if the file doesn't exist?
189
        //XXX handle error return value (-1)
239
            for (PollFd fd : polls) {
190
        LOG.log(Level.FINEST, "addWatch{0} res: {1}", new Object[]{path, id});
240
                id = IMPL.inotify_add_watch(fd.fd, path,
191
        if (id <= 0) {
241
                        InotifyImpl.IN_CREATE | InotifyImpl.IN_MOVED_TO |
192
            // 28 == EINOSPC
242
                        InotifyImpl.IN_DELETE | InotifyImpl.IN_MOVED_FROM |
193
            int errno = NativeLibrary.getInstance("c").getFunction("errno").getInt(0); // NOI18N
243
                        InotifyImpl.IN_MODIFY | InotifyImpl.IN_ATTRIB);
194
            throw new IOException("addWatch on " + path + " errno: " + errno); // NOI18N
244
                //XXX handle error return value (-1)
245
                if (id <= 0) {
246
                    int errno = NativeLibrary.getInstance("c").getFunction("errno").getInt(0); // NOI18N
247
                    LOG.log(Level.FINE, "addWatch error {3}/{1} at {0} on {2}", new Object[]{path, id, fd, errno});
248
                    if (errno == 28) {
249
                        // 28 == EINOSPC
250
                        continue;
251
                    }
252
                    throw new IOException("addWatch on " + path + " errno: " + errno); // NOI18N
253
                }
254
                LOG.log(Level.FINEST, "addWatch{0} res: {1} on {2}", new Object[]{path, id, fd});
255
                from = fd;
256
                break OK;
257
            }
258
            LOG.log(Level.WARNING, "Expanding list of iNotify instances from {0}", polls.length);
259
            synchronized (this) {
260
                arr = new ArrayList<PollFd>(arr);
261
                final PollFd pollFd = new PollFd(allocFD());
262
                arr.add(pollFd);
263
                polls = arr.toArray(new PollFd[0]);
264
                LOG.log(Level.FINE, "Current polls: {0}", arr);
265
            }
195
        }
266
        }
196
267
197
        LKey newKey = map.get(id);
268
        LKey newKey = map.get(id);
198
        if (newKey == null) {
269
        if (newKey == null) {
199
            newKey = new LKey(id, path);
270
            newKey = new LKey(id, path, from);
200
            map.put(id, newKey);
271
            map.put(id, newKey);
201
        }
272
        }
202
        return newKey;
273
        return newKey;
Lines 204-209 Link Here
204
275
205
    @Override public void removeWatch(LKey lkey) {
276
    @Override public void removeWatch(LKey lkey) {
206
        map.remove(lkey.id);
277
        map.remove(lkey.id);
207
        IMPL.inotify_rm_watch(fd, lkey.id);
278
        IMPL.inotify_rm_watch(lkey.from.fd, lkey.id);
208
    }
279
    }
209
}
280
}

Return to bug 197966