History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/nio/fs/AbstractWatchKey.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/nio/fs/AbstractWatchKey.java+223−0
@@ -0,0 +1,223 @@
1+/*
2+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.nio.fs;
27+
28+import java.nio.file.*;
29+import java.util.*;
30+
31+/**
32+ * Base implementation class for watch keys.
33+ */
34+
35+abstract class AbstractWatchKey implements WatchKey {
36+
37+ /**
38+ * Maximum size of event list (in the future this may be tunable)
39+ */
40+ static final int MAX_EVENT_LIST_SIZE = 512;
41+
42+ /**
43+ * Special event to signal overflow
44+ */
45+ static final Event<Object> OVERFLOW_EVENT =
46+ new Event<Object>(StandardWatchEventKinds.OVERFLOW, null);
47+
48+ /**
49+ * Possible key states
50+ */
51+ private static enum State { READY, SIGNALLED };
52+
53+ // reference to watcher
54+ private final AbstractWatchService watcher;
55+
56+ // reference to the original directory
57+ private final Path dir;
58+
59+ // key state
60+ private State state;
61+
62+ // pending events
63+ private List<WatchEvent<?>> events;
64+
65+ // maps a context to the last event for the context (iff the last queued
66+ // event for the context is an ENTRY_MODIFY event).
67+ private Map<Object,WatchEvent<?>> lastModifyEvents;
68+
69+ protected AbstractWatchKey(Path dir, AbstractWatchService watcher) {
70+ this.watcher = watcher;
71+ this.dir = dir;
72+ this.state = State.READY;
73+ this.events = new ArrayList<WatchEvent<?>>();
74+ this.lastModifyEvents = new HashMap<Object,WatchEvent<?>>();
75+ }
76+
77+ final AbstractWatchService watcher() {
78+ return watcher;
79+ }
80+
81+ /**
82+ * Return the original watchable (Path)
83+ */
84+ @Override
85+ public Path watchable() {
86+ return dir;
87+ }
88+
89+ /**
90+ * Enqueues this key to the watch service
91+ */
92+ final void signal() {
93+ synchronized (this) {
94+ if (state == State.READY) {
95+ state = State.SIGNALLED;
96+ watcher.enqueueKey(this);
97+ }
98+ }
99+ }
100+
101+ /**
102+ * Adds the event to this key and signals it.
103+ */
104+ @SuppressWarnings("unchecked")
105+ final void signalEvent(WatchEvent.Kind<?> kind, Object context) {
106+ boolean isModify = (kind == StandardWatchEventKinds.ENTRY_MODIFY);
107+ synchronized (this) {
108+ int size = events.size();
109+ if (size > 0) {
110+ // if the previous event is an OVERFLOW event or this is a
111+ // repeated event then we simply increment the counter
112+ WatchEvent<?> prev = events.get(size-1);
113+ if ((prev.kind() == StandardWatchEventKinds.OVERFLOW) ||
114+ ((kind == prev.kind() &&
115+ Objects.equals(context, prev.context()))))
116+ {
117+ ((Event<?>)prev).increment();
118+ return;
119+ }
120+
121+ // if this is a modify event and the last entry for the context
122+ // is a modify event then we simply increment the count
123+ if (!lastModifyEvents.isEmpty()) {
124+ if (isModify) {
125+ WatchEvent<?> ev = lastModifyEvents.get(context);
126+ if (ev != null) {
127+ assert ev.kind() == StandardWatchEventKinds.ENTRY_MODIFY;
128+ ((Event<?>)ev).increment();
129+ return;
130+ }
131+ } else {
132+ // not a modify event so remove from the map as the
133+ // last event will no longer be a modify event.
134+ lastModifyEvents.remove(context);
135+ }
136+ }
137+
138+ // if the list has reached the limit then drop pending events
139+ // and queue an OVERFLOW event
140+ if (size >= MAX_EVENT_LIST_SIZE) {
141+ kind = StandardWatchEventKinds.OVERFLOW;
142+ isModify = false;
143+ context = null;
144+ }
145+ }
146+
147+ // non-repeated event
148+ Event<Object> ev =
149+ new Event<Object>((WatchEvent.Kind<Object>)kind, context);
150+ if (isModify) {
151+ lastModifyEvents.put(context, ev);
152+ } else if (kind == StandardWatchEventKinds.OVERFLOW) {
153+ // drop all pending events
154+ events.clear();
155+ lastModifyEvents.clear();
156+ }
157+ events.add(ev);
158+ signal();
159+ }
160+ }
161+
162+ @Override
163+ public final List<WatchEvent<?>> pollEvents() {
164+ synchronized (this) {
165+ List<WatchEvent<?>> result = events;
166+ events = new ArrayList<WatchEvent<?>>();
167+ lastModifyEvents.clear();
168+ return result;
169+ }
170+ }
171+
172+ @Override
173+ public final boolean reset() {
174+ synchronized (this) {
175+ if (state == State.SIGNALLED && isValid()) {
176+ if (events.isEmpty()) {
177+ state = State.READY;
178+ } else {
179+ // pending events so re-queue key
180+ watcher.enqueueKey(this);
181+ }
182+ }
183+ return isValid();
184+ }
185+ }
186+
187+ /**
188+ * WatchEvent implementation
189+ */
190+ private static class Event<T> implements WatchEvent<T> {
191+ private final WatchEvent.Kind<T> kind;
192+ private final T context;
193+
194+ // synchronize on watch key to access/increment count
195+ private int count;
196+
197+ Event(WatchEvent.Kind<T> type, T context) {
198+ this.kind = type;
199+ this.context = context;
200+ this.count = 1;
201+ }
202+
203+ @Override
204+ public WatchEvent.Kind<T> kind() {
205+ return kind;
206+ }
207+
208+ @Override
209+ public T context() {
210+ return context;
211+ }
212+
213+ @Override
214+ public int count() {
215+ return count;
216+ }
217+
218+ // for repeated events
219+ void increment() {
220+ count++;
221+ }
222+ }
223+}