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 185526
Collapse All | Expand All

(-)a/masterfs/apichanges.xml (+17 lines)
Lines 46-51 Link Here
46
        <apidef name="masterfs">MasterFileSystem API</apidef>
46
        <apidef name="masterfs">MasterFileSystem API</apidef>
47
    </apidefs>
47
    </apidefs>
48
    <changes>
48
    <changes>
49
        <change id="priority-io">
50
            <api name="masterfs"/>
51
            <summary><code>ProvidedExtensions.priorityIO</code> to suspend background refresh</summary>
52
            <version major="2" minor="25"/>
53
            <date day="12" month="5" year="2010"/>
54
            <author login="jtulach"/>
55
            <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
56
            <description>
57
                <p>
58
                    <code>ProvidedExtensions.priorityIO</code> allows
59
                    parsing API to suspend background I/O activity after refresh
60
                    of main window.
61
                </p>
62
            </description>
63
            <class package="org.netbeans.modules.masterfs.providers" name="ProvidedExtensions"/>
64
            <issue number="181684"/>
65
        </change>
49
        <change id="recursive-control">
66
        <change id="recursive-control">
50
            <api name="masterfs"/>
67
            <api name="masterfs"/>
51
            <summary><code>ProvidedExtensions.refreshRecursively</code> was added.</summary>
68
            <summary><code>ProvidedExtensions.refreshRecursively</code> was added.</summary>
(-)a/masterfs/manifest.mf (-1 / +1 lines)
Lines 1-7 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.masterfs/2
2
OpenIDE-Module: org.netbeans.modules.masterfs/2
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/masterfs/resources/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/masterfs/resources/Bundle.properties
4
OpenIDE-Module-Specification-Version: 2.24
4
OpenIDE-Module-Specification-Version: 2.25
5
AutoUpdate-Show-In-Client: false
5
AutoUpdate-Show-In-Client: false
6
AutoUpdate-Essential-Module: true
6
AutoUpdate-Essential-Module: true
7
7
(-)a/masterfs/src/org/netbeans/modules/masterfs/filebasedfs/utils/FileChangedManager.java (-1 / +13 lines)
Lines 42-47 Link Here
42
import java.security.Permission;
42
import java.security.Permission;
43
import java.util.concurrent.ConcurrentHashMap;
43
import java.util.concurrent.ConcurrentHashMap;
44
import java.util.concurrent.atomic.AtomicBoolean;
44
import java.util.concurrent.atomic.AtomicBoolean;
45
import java.util.concurrent.atomic.AtomicInteger;
45
import java.util.logging.Level;
46
import java.util.logging.Level;
46
import java.util.logging.Logger;
47
import java.util.logging.Logger;
47
import org.netbeans.modules.masterfs.filebasedfs.naming.NamingFactory;
48
import org.netbeans.modules.masterfs.filebasedfs.naming.NamingFactory;
Lines 58-67 Link Here
58
    private static final int CREATE_HINT = 2;
59
    private static final int CREATE_HINT = 2;
59
    private static final int DELETE_HINT = 1;
60
    private static final int DELETE_HINT = 1;
60
    private static final int AMBIGOUS_HINT = 3;
61
    private static final int AMBIGOUS_HINT = 3;
62
61
    private final ConcurrentHashMap<Integer,Integer> hints = new ConcurrentHashMap<Integer,Integer>();
63
    private final ConcurrentHashMap<Integer,Integer> hints = new ConcurrentHashMap<Integer,Integer>();
62
    private long shrinkTime = System.currentTimeMillis();
64
    private long shrinkTime = System.currentTimeMillis();
63
    private static volatile long ioTime = -1;
65
    private static volatile long ioTime = -1;
64
    private static volatile int ioLoad;
66
    private static volatile int ioLoad;
67
    private static final AtomicInteger priorityIO = new AtomicInteger();
65
    private static final ThreadLocal<Integer> IDLE_IO = new ThreadLocal<Integer>();
68
    private static final ThreadLocal<Integer> IDLE_IO = new ThreadLocal<Integer>();
66
    private static final ThreadLocal<Runnable> IDLE_CALL = new ThreadLocal<Runnable>();
69
    private static final ThreadLocal<Runnable> IDLE_CALL = new ThreadLocal<Runnable>();
67
    private static final ThreadLocal<AtomicBoolean> IDLE_ON = new ThreadLocal<AtomicBoolean>();
70
    private static final ThreadLocal<AtomicBoolean> IDLE_ON = new ThreadLocal<AtomicBoolean>();
Lines 140-145 Link Here
140
        return retval;
143
        return retval;
141
    }
144
    }
142
145
146
    public static void priorityIO(Runnable run) {
147
        try {
148
            priorityIO.incrementAndGet();
149
            run.run();
150
        } finally {
151
            priorityIO.decrementAndGet();
152
        }
153
    }
154
143
    private static boolean isIdleIO() {
155
    private static boolean isIdleIO() {
144
        return IDLE_IO.get() != null;
156
        return IDLE_IO.get() != null;
145
    }
157
    }
Lines 170-176 Link Here
170
                throw new InterruptedException(msg);
182
                throw new InterruptedException(msg);
171
            }
183
            }
172
            int l = pingIO(0);
184
            int l = pingIO(0);
173
            if (l < load) {
185
            if (l < load && priorityIO.get() == 0) {
174
                return;
186
                return;
175
            }
187
            }
176
            synchronized (IDLE_IO) {
188
            synchronized (IDLE_IO) {
(-)a/masterfs/src/org/netbeans/modules/masterfs/providers/ProvidedExtensions.java (+12 lines)
Lines 44-49 Link Here
44
import java.io.File;
44
import java.io.File;
45
import java.io.IOException;
45
import java.io.IOException;
46
import java.util.List;
46
import java.util.List;
47
import org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager;
47
import org.openide.filesystems.FileObject;
48
import org.openide.filesystems.FileObject;
48
49
49
/**
50
/**
Lines 209-212 Link Here
209
    public long refreshRecursively(File dir, long lastTimeStamp, List<? super File> children) {
210
    public long refreshRecursively(File dir, long lastTimeStamp, List<? super File> children) {
210
        return -1;
211
        return -1;
211
    }
212
    }
213
214
    /** Allows registered exceptions to execute some I/O priority action.
215
     * This will stop all other "idle I/O" operations (like background refresh
216
     * after window is activated).
217
     *
218
     * @param run the runnable to run
219
     * @since 2.35
220
     */
221
    public final void priorityIO(Runnable run) {
222
        FileChangedManager.priorityIO(run);
223
    }
212
}
224
}
(-)a7a9ba5aba75 (+216 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.masterfs;
41
42
import java.awt.event.ActionEvent;
43
import java.io.File;
44
import java.io.FileOutputStream;
45
import java.lang.ref.Reference;
46
import java.lang.ref.WeakReference;
47
import java.util.ArrayList;
48
import java.util.List;
49
import java.util.logging.Level;
50
import java.util.logging.Logger;
51
import org.netbeans.junit.NbTestCase;
52
import org.netbeans.junit.RandomlyFails;
53
import org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager;
54
import org.openide.filesystems.FileChangeAdapter;
55
import org.openide.filesystems.FileEvent;
56
import org.openide.filesystems.FileObject;
57
import org.openide.filesystems.FileUtil;
58
import org.openide.util.Exceptions;
59
import org.openide.util.RequestProcessor;
60
61
public class SlowRefreshAndPriorityIOTest extends NbTestCase {
62
    private Logger LOG;
63
    private FileObject testFolder;
64
65
    public SlowRefreshAndPriorityIOTest(String testName) {
66
        super(testName);
67
    }
68
69
    @Override
70
    protected Level logLevel() {
71
        return Level.FINE;
72
    }
73
74
    @Override
75
    protected void setUp() throws Exception {
76
        clearWorkDir();
77
78
79
        LOG = Logger.getLogger("test." + getName());
80
        Logger.getLogger("org.openide.util.Mutex").setUseParentHandlers(false);
81
82
        File dir = new File(getWorkDir(), "test");
83
        dir.mkdirs();
84
        testFolder = FileUtil.toFileObject(dir);
85
        assertNotNull("Test folder created", testFolder);
86
87
        System.setSecurityManager(new FileChangedManager());
88
    }
89
90
    public void testRefreshCanBeSuspendedByPriorityIO() throws Exception {
91
        long lm = System.currentTimeMillis();
92
        LOG.info("starting testRefreshCanBeSuspended " + lm);
93
        FileObject fileObject1 = testFolder.createData("fileObject1");
94
        assertNotNull("Just to initialize the stamp", lm);
95
        FileObject[] arr = testFolder.getChildren();
96
        assertEquals("One child", 1, arr.length);
97
        assertEquals("Right child", fileObject1, arr[0]);
98
99
        File file = FileUtil.toFile(fileObject1);
100
        assertNotNull("File found", file);
101
        Reference<FileObject> ref = new WeakReference<FileObject>(fileObject1);
102
        arr = null;
103
        fileObject1 = null;
104
        assertGC("File Object can disappear", ref);
105
106
        class L extends FileChangeAdapter {
107
            int cnt;
108
            FileEvent event;
109
110
            @Override
111
            public void fileChanged(FileEvent fe) {
112
                LOG.info("file change " + fe.getFile());
113
                cnt++;
114
                event = fe;
115
            }
116
        }
117
        L listener = new L();
118
        testFolder.addRecursiveListener(listener);
119
        
120
        Thread.sleep(1000);
121
122
        FileOutputStream os = new FileOutputStream(file);
123
        os.write(10);
124
        os.close();
125
126
        if (lm > file.lastModified() - 50) {
127
            fail("New modification time shall be at last 50ms after the original one: " + (file.lastModified() - lm));
128
        }
129
130
        Object obj = testFolder.getFileSystem().getRoot().getAttribute("refreshSlow");
131
        assertNotNull("Refresh attribute found", obj);
132
        assertTrue("It is instance of runnable:  " + obj, obj instanceof Runnable);
133
134
        Runnable r = (Runnable)obj;
135
        class AE extends ActionEvent implements Runnable {
136
            List<FileObject> files = new ArrayList<FileObject>();
137
            boolean boosted;
138
            boolean finished;
139
            int goingIdle;
140
            
141
            public AE() {
142
                super("", 0, "");
143
            }
144
145
            @Override
146
            public void setSource(Object newSource) {
147
                LOG.log(Level.INFO, "Set source called: {0}", newSource);
148
                assertTrue(newSource instanceof Object[]);
149
                Object[] arr = (Object[])newSource;
150
                assertTrue("Three elements at leat ", 3 <= arr.length);
151
                assertTrue("first is int", arr[0] instanceof Integer);
152
                assertTrue("2nd is int", arr[1] instanceof Integer);
153
                assertTrue("3rd is fileobject", arr[2] instanceof FileObject);
154
                files.add((FileObject)arr[2]);
155
                super.setSource(newSource);
156
            }
157
158
            @Override
159
            public void run() {
160
                goingIdle++;
161
            }
162
163
            public synchronized void waitBoosted() throws Exception {
164
                while (!boosted) {
165
                    wait();
166
                }
167
            }
168
169
            public synchronized void notifyBoosted() {
170
                boosted = true;
171
                notifyAll();
172
            }
173
        }
174
        final AE counter = new AE();
175
176
        LOG.info("Posting AE into RP");
177
        // starts 5s of disk checking
178
        RequestProcessor.Task task = RequestProcessor.getDefault().post(new Runnable() {
179
            boolean snd;
180
            @Override
181
            public void run() {
182
                if (!snd) {
183
                    snd = true;
184
                    FileChangedManager.priorityIO(this);
185
                } else {
186
                    counter.notifyBoosted();
187
                    try {
188
                        Thread.sleep(5000);
189
                        counter.finished = true;
190
                    } catch (InterruptedException ex) {
191
                        Exceptions.printStackTrace(ex);
192
                    }
193
                }
194
            }
195
        });
196
197
        // connect together
198
        r.equals(counter);
199
200
        LOG.info("Waiting for I/O boost");
201
        counter.waitBoosted();
202
        LOG.info("Starting refresh");
203
        // do the refresh
204
        r.run();
205
        LOG.info("Refresh finished");
206
207
        assertTrue("Background I/O access needs to stop before we finish our task", counter.finished);
208
209
        assertEquals("Change notified", 1, listener.cnt);
210
        assertEquals("Right file", file, FileUtil.toFile(listener.event.getFile()));
211
        assertEquals("Right source", file.getParentFile(), FileUtil.toFile((FileObject)listener.event.getSource()));
212
        if (counter.goingIdle == 0) {
213
            fail("The I/O subsystem shall notify the action that it went idle at least once");
214
        }
215
    }
216
}

Return to bug 185526