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

(-)a/dlight.nativeexecution/src/org/netbeans/modules/nativeexecution/api/util/RemoteStatistics.java (+24 lines)
Lines 45-56 Link Here
45
import java.io.File;
45
import java.io.File;
46
import java.io.FileNotFoundException;
46
import java.io.FileNotFoundException;
47
import java.io.PrintStream;
47
import java.io.PrintStream;
48
import java.util.List;
48
import java.util.concurrent.ArrayBlockingQueue;
49
import java.util.concurrent.ArrayBlockingQueue;
49
import java.util.concurrent.BlockingQueue;
50
import java.util.concurrent.BlockingQueue;
50
import java.util.concurrent.Callable;
51
import java.util.concurrent.Callable;
51
import java.util.concurrent.atomic.AtomicBoolean;
52
import java.util.concurrent.atomic.AtomicBoolean;
52
import java.util.concurrent.atomic.AtomicLong;
53
import java.util.concurrent.atomic.AtomicLong;
53
import java.util.concurrent.atomic.AtomicReference;
54
import java.util.concurrent.atomic.AtomicReference;
55
import org.netbeans.modules.nativeexecution.api.ExecutionEnvironment;
54
import org.netbeans.modules.nativeexecution.jsch.MeasurableSocketFactory;
56
import org.netbeans.modules.nativeexecution.jsch.MeasurableSocketFactory;
55
import org.netbeans.modules.nativeexecution.jsch.MeasurableSocketFactory.IOListener;
57
import org.netbeans.modules.nativeexecution.jsch.MeasurableSocketFactory.IOListener;
56
import org.openide.modules.OnStop;
58
import org.openide.modules.OnStop;
Lines 61-66 Link Here
61
@OnStop
63
@OnStop
62
public final class RemoteStatistics implements Callable<Boolean> {
64
public final class RemoteStatistics implements Callable<Boolean> {
63
65
66
    private static final String BREAK_UPLOADS_FLAG_FILE = System.getProperty("break.uploads"); // NOI18N
64
    public static final boolean COLLECT_STATISTICS = Boolean.parseBoolean(System.getProperty("jsch.statistics", "false")); // NOI18N
67
    public static final boolean COLLECT_STATISTICS = Boolean.parseBoolean(System.getProperty("jsch.statistics", "false")); // NOI18N
65
    public static final boolean COLLECT_STACKS = COLLECT_STATISTICS && Boolean.parseBoolean(System.getProperty("jsch.statistics.stacks", "false")); // NOI18N
68
    public static final boolean COLLECT_STACKS = COLLECT_STATISTICS && Boolean.parseBoolean(System.getProperty("jsch.statistics.stacks", "false")); // NOI18N
66
    private static final TrafficCounters trafficCounters = new TrafficCounters();
69
    private static final TrafficCounters trafficCounters = new TrafficCounters();
Lines 274-283 Link Here
274
        @Override
277
        @Override
275
        public void bytesUploaded(int bytes) {
278
        public void bytesUploaded(int bytes) {
276
            RemoteMeasurementsRef stat = reschedule();
279
            RemoteMeasurementsRef stat = reschedule();
280
            checkBreakUploads();
277
            stat.stat.bytesUploaded(bytes);
281
            stat.stat.bytesUploaded(bytes);
278
282
279
        }
283
        }
280
284
285
        private void checkBreakUploads() {
286
            if (BREAK_UPLOADS_FLAG_FILE != null && new File(BREAK_UPLOADS_FLAG_FILE).exists()) {
287
                boolean isOpenW = false;
288
                for (StackTraceElement el : Thread.currentThread().getStackTrace()) {
289
                    if (el.getClassName().endsWith(".ChannelSftp")) { //
290
                        if (el.getMethodName().equals("sendOPENW")) {
291
                            isOpenW = true;
292
                            break;
293
                        }
294
                    }
295
                }
296
                if (isOpenW) {
297
                    List<ExecutionEnvironment> recentConnections = ConnectionManager.getInstance().getRecentConnections();
298
                    for (ExecutionEnvironment env : recentConnections) {
299
                        ConnectionManager.getInstance().disconnect(env);
300
                    }
301
                }
302
            }
303
        }
304
281
        @Override
305
        @Override
282
        public void bytesDownloaded(int bytes) {
306
        public void bytesDownloaded(int bytes) {
283
            RemoteMeasurementsRef stat = reschedule();
307
            RemoteMeasurementsRef stat = reschedule();
(-)29da0cda97df (+191 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.remote.impl.fs;
43
44
import java.io.BufferedReader;
45
import java.io.BufferedWriter;
46
import java.io.File;
47
import java.io.FileNotFoundException;
48
import java.io.FileReader;
49
import java.io.FileWriter;
50
import java.io.IOException;
51
import java.util.ArrayList;
52
import java.util.Collection;
53
import java.util.HashSet;
54
import java.util.List;
55
import java.util.Set;
56
import org.netbeans.modules.remote.impl.RemoteLogger;
57
58
/**
59
 *
60
 * @author vkvashin
61
 */
62
public final class PendingUploadsManager {
63
64
    private final File storageFile;
65
    private final Object lock = new Object();
66
    private final RemoteFileObjectFactory fileObjectFactory;
67
    private final RemoteDirectory rootDirectory;
68
69
    /** files that are now being uploaded */
70
    private final Set<String> pendingFiles = new HashSet<String>();
71
72
    /** files that failed to upload */
73
    private final Set<String> failedFiles = new HashSet<String>();
74
75
    public PendingUploadsManager(RemoteFileObjectFactory fileObjectFactory, RemoteDirectory rootDirectory, File storageFile) {
76
        this.storageFile = storageFile;
77
        this.fileObjectFactory = fileObjectFactory;
78
        this.rootDirectory = rootDirectory;
79
    }
80
81
    public void addPendingUpload(RemotePlainFile file) {
82
        synchronized (lock) {
83
            failedFiles.remove(file.getPath());
84
            pendingFiles.add(file.getPath());
85
            save();
86
        }
87
    }
88
89
    public void addFailedUpload(RemotePlainFile file) {
90
        synchronized (lock) {
91
            pendingFiles.remove(file.getPath());
92
            failedFiles.add(file.getPath());
93
            save();
94
        }
95
    }
96
97
    public void removePendingOrFailedUpload(RemotePlainFile file) {
98
        synchronized (lock) {
99
            pendingFiles.remove(file.getPath());
100
            failedFiles.remove(file.getPath());
101
            save();
102
        }
103
    }
104
105
    public boolean isPendingOrFailedUpload(String path) {
106
        synchronized (lock) {
107
            return pendingFiles.contains(path) || failedFiles.contains(path);
108
        }
109
    }
110
111
    public void load() {
112
        synchronized (lock) {
113
            if (!storageFile.exists()) {
114
                return;
115
            }
116
            BufferedReader isr = null;
117
            try {
118
                isr = new BufferedReader(new FileReader(storageFile));
119
                String line;
120
                while ((line = isr.readLine()) != null) {
121
                    line = line.trim();
122
                    if (!line.isEmpty()) {
123
                        failedFiles.add(line);
124
                    }
125
                }
126
            } catch (FileNotFoundException e) {
127
                e.printStackTrace(System.err);
128
            } catch (IOException e) {
129
                e.printStackTrace(System.err);
130
            } finally {
131
                if (isr != null) {
132
                    try {
133
                        isr.close();
134
                    } catch (IOException e) {
135
                        e.printStackTrace(System.err);
136
                    }
137
                }
138
            }
139
        }
140
    }
141
142
    public void save() {
143
        synchronized (lock) {
144
            BufferedWriter wr = null;
145
            try {
146
                wr = new BufferedWriter(new FileWriter(storageFile));
147
                for (String path : pendingFiles) {
148
                    wr.write(path.trim());
149
                    wr.newLine();
150
                }
151
                for (String path : failedFiles) {
152
                    wr.write(path.trim());
153
                    wr.newLine();
154
                }
155
            } catch (IOException e) {
156
                e.printStackTrace(System.err);
157
            } finally {
158
                if (wr != null) {
159
                    try {
160
                        wr.close();
161
                    } catch (IOException e) {
162
                        e.printStackTrace(System.err);
163
                    }
164
                }
165
            }
166
        }
167
    }
168
169
    public Collection<RemotePlainFile> getFailedFiles() {
170
        List<RemotePlainFile> files = new ArrayList<RemotePlainFile>();
171
        synchronized (lock) {
172
            List<String> pathsToRemove = new ArrayList<String>();
173
            for (String path : failedFiles) {
174
                RemoteFileObjectBase fo = fileObjectFactory.getCachedFileObject(path);
175
                if (fo == null) {
176
                    RemoteFileObject rfo = rootDirectory.getFileObject(path, new HashSet<String>());
177
                    if (rfo != null) {
178
                        fo = rfo.getImplementor();
179
                    }
180
                }
181
                if (fo instanceof RemotePlainFile) {
182
                    files.add((RemotePlainFile) fo);
183
                } else { // null or not RemotePlainFile
184
                    pathsToRemove.add(path);
185
                }
186
            }
187
            failedFiles.removeAll(pathsToRemove);
188
        }
189
        return files;
190
    }
191
}
(-)a/dlight.remote.impl/src/org/netbeans/modules/remote/impl/fs/RefreshManager.java (-4 / +7 lines)
Lines 68-73 Link Here
68
68
69
    private final ExecutionEnvironment env;
69
    private final ExecutionEnvironment env;
70
    private final RemoteFileObjectFactory factory;
70
    private final RemoteFileObjectFactory factory;
71
    private final PendingUploadsManager pendingUploadsManager;
71
    private final RequestProcessor.Task updateTask;
72
    private final RequestProcessor.Task updateTask;
72
    
73
    
73
    private final LinkedList<RemoteFileObjectBase> queue = new LinkedList<RemoteFileObjectBase>();
74
    private final LinkedList<RemoteFileObjectBase> queue = new LinkedList<RemoteFileObjectBase>();
Lines 144-154 Link Here
144
        }
145
        }
145
    }
146
    }
146
147
147
    public RefreshManager(ExecutionEnvironment env, RemoteFileObjectFactory factory) {
148
    public RefreshManager(ExecutionEnvironment env, RemoteFileObjectFactory factory, PendingUploadsManager pendingUploadsManager) {
148
        this.env = env;
149
        this.env = env;
149
        this.factory = factory;
150
        this.factory = factory;
151
        this.pendingUploadsManager = pendingUploadsManager;
150
        updateTask = new RequestProcessor("Remote File System RefreshManager " + env.getDisplayName(), 1).create(new RefreshWorker(false)); //NOI18N
152
        updateTask = new RequestProcessor("Remote File System RefreshManager " + env.getDisplayName(), 1).create(new RefreshWorker(false)); //NOI18N
151
    }        
153
    }
152
    
154
    
153
    public void scheduleRefreshOnFocusGained(Collection<RemoteFileObjectBase> fileObjects) {
155
    public void scheduleRefreshOnFocusGained(Collection<RemoteFileObjectBase> fileObjects) {
154
        if (REFRESH_ON_FOCUS) {
156
        if (REFRESH_ON_FOCUS) {
Lines 158-169 Link Here
158
    }
160
    }
159
161
160
    public void scheduleRefreshOnConnect(Collection<RemoteFileObjectBase> fileObjects) {
162
    public void scheduleRefreshOnConnect(Collection<RemoteFileObjectBase> fileObjects) {
163
        scheduleRefreshImpl(pendingUploadsManager.getFailedFiles(), false);
161
        if (REFRESH_ON_CONNECT) {
164
        if (REFRESH_ON_CONNECT) {
162
            RemoteLogger.getInstance().log(Level.FINE, "Refresh on connect schedulled for {0} directories on {1}", new Object[]{fileObjects.size(), env});
165
            RemoteLogger.getInstance().log(Level.FINE, "Refresh on connect schedulled for {0} directories on {1}", new Object[]{fileObjects.size(), env});
163
            scheduleRefreshImpl(filterDirectories(fileObjects), false);
166
            scheduleRefreshImpl(filterDirectories(fileObjects), false);
164
        }
167
        }
165
    }
168
    }
166
    
169
167
    private Collection<RemoteFileObjectBase> filterDirectories(Collection<RemoteFileObjectBase> fileObjects) {
170
    private Collection<RemoteFileObjectBase> filterDirectories(Collection<RemoteFileObjectBase> fileObjects) {
168
        Collection<RemoteFileObjectBase> result = new TreeSet<RemoteFileObjectBase>(new PathComparator(true));
171
        Collection<RemoteFileObjectBase> result = new TreeSet<RemoteFileObjectBase>(new PathComparator(true));
169
        for (RemoteFileObjectBase fo : fileObjects) {
172
        for (RemoteFileObjectBase fo : fileObjects) {
Lines 223-229 Link Here
223
        }
226
        }
224
    }
227
    }
225
    
228
    
226
    private void scheduleRefreshImpl(Collection<RemoteFileObjectBase> fileObjects, boolean toTheHead) {
229
    private void scheduleRefreshImpl(Collection<? extends RemoteFileObjectBase> fileObjects, boolean toTheHead) {
227
        if ( ! ConnectionManager.getInstance().isConnectedTo(env)) {
230
        if ( ! ConnectionManager.getInstance().isConnectedTo(env)) {
228
            RemoteLogger.getInstance().warning("scheduleRefresh(Collection<FileObject>) is called while host is not connected");
231
            RemoteLogger.getInstance().warning("scheduleRefresh(Collection<FileObject>) is called while host is not connected");
229
        }        
232
        }        
(-)a/dlight.remote.impl/src/org/netbeans/modules/remote/impl/fs/RemoteDirectory.java (-14 / +21 lines)
Lines 405-411 Link Here
405
        List<DirEntry> entries = storage.listValid();
405
        List<DirEntry> entries = storage.listValid();
406
        List<RemoteFileObjectBase> result = new ArrayList<RemoteFileObjectBase>(entries.size());
406
        List<RemoteFileObjectBase> result = new ArrayList<RemoteFileObjectBase>(entries.size());
407
        for (DirEntry entry : entries) {
407
        for (DirEntry entry : entries) {
408
            String path = getPath() + '/' + entry.getName();
408
            String path = getAbsolutePath(entry);
409
            RemoteFileObjectBase fo = getFileSystem().getFactory().getCachedFileObject(path);
409
            RemoteFileObjectBase fo = getFileSystem().getFactory().getCachedFileObject(path);
410
            if (fo != null) {
410
            if (fo != null) {
411
                result.add(fo);
411
                result.add(fo);
Lines 698-711 Link Here
698
                                    changed = fire = true;
698
                                    changed = fire = true;
699
                                    File entryCache = new File(getCache(), oldEntry.getCache());
699
                                    File entryCache = new File(getCache(), oldEntry.getCache());
700
                                    if (entryCache.exists()) {
700
                                    if (entryCache.exists()) {
701
                                        if (trace) {trace("removing cache for updated file {0}", entryCache.getAbsolutePath());} // NOI18N
701
                                        if (!getFileSystem().getPendingUploadsManager().isPendingOrFailedUpload(getAbsolutePath(oldEntry))) {
702
                                        entryCache.delete(); // TODO: We must just mark it as invalid instead of physically deleting cache file...
702
                                            if (trace) {trace("removing cache for updated file {0}", entryCache.getAbsolutePath());} // NOI18N
703
                                            entryCache.delete(); // TODO: We must just mark it as invalid instead of physically deleting cache file...
704
                                        }
703
                                    }
705
                                    }
704
                                }
706
                                }
705
                            } 
707
                            } 
706
                            if (!equals(newEntry.getLinkTarget(), oldEntry.getLinkTarget())) {
708
                            if (!equals(newEntry.getLinkTarget(), oldEntry.getLinkTarget())) {
707
                                changed = fire = true; // TODO: we forgot old link path, probably should be passed to change event 
709
                                changed = fire = true; // TODO: we forgot old link path, probably should be passed to change event 
708
                                getFileSystem().getFactory().setLink(this, getPath() + '/' + newEntry.getName(), newEntry.getLinkTarget());
710
                                getFileSystem().getFactory().setLink(this, getAbsolutePath(newEntry), newEntry.getLinkTarget());
709
                            } 
711
                            } 
710
                            if (!newEntry.getAccessAsString().equals(oldEntry.getAccessAsString())) {
712
                            if (!newEntry.getAccessAsString().equals(oldEntry.getAccessAsString())) {
711
                                changed = fire = true;
713
                                changed = fire = true;
Lines 808-814 Link Here
808
                    fireRemoteFileObjectCreated(fo.getOwnerFileObject());
810
                    fireRemoteFileObjectCreated(fo.getOwnerFileObject());
809
                }
811
                }
810
                for (DirEntry entry : entriesToFireChanged) {
812
                for (DirEntry entry : entriesToFireChanged) {
811
                    RemoteFileObjectBase fo = getFileSystem().getFactory().getCachedFileObject(getPath() + '/' + entry.getName());
813
                    RemoteFileObjectBase fo = getFileSystem().getFactory().getCachedFileObject(getAbsolutePath(entry));
812
                    if (fo != null) {
814
                    if (fo != null) {
813
                        RemoteFileObject ownerFileObject = fo.getOwnerFileObject();
815
                        RemoteFileObject ownerFileObject = fo.getOwnerFileObject();
814
                        fireFileChangedEvent(getListeners(), new FileEvent(ownerFileObject, ownerFileObject, false, ownerFileObject.lastModified().getTime()));
816
                        fireFileChangedEvent(getListeners(), new FileEvent(ownerFileObject, ownerFileObject, false, ownerFileObject.lastModified().getTime()));
Lines 851-858 Link Here
851
                }
853
                }
852
                synchronized (refLock) {
854
                synchronized (refLock) {
853
                    storageRef = new SoftReference<DirectoryStorage>(newStorage);
855
                    storageRef = new SoftReference<DirectoryStorage>(newStorage);
854
                }
856
                }                
855
                fo.setPendingRemoteDelivery(false);
856
            }
857
            }
857
        } finally {
858
        } finally {
858
            writeLock.unlock();
859
            writeLock.unlock();
Lines 1021-1035 Link Here
1021
                                    changed = fire = true;
1022
                                    changed = fire = true;
1022
                                    File entryCache = new File(getCache(), oldEntry.getCache());
1023
                                    File entryCache = new File(getCache(), oldEntry.getCache());
1023
                                    if (entryCache.exists()) {
1024
                                    if (entryCache.exists()) {
1024
                                        if (trace) { trace("removing cache for updated file {0}", entryCache.getAbsolutePath()); } // NOI18N
1025
                                        if (!getFileSystem().getPendingUploadsManager().isPendingOrFailedUpload(getAbsolutePath(oldEntry))) {
1025
                                        entryCache.delete(); // TODO: We must just mark it as invalid instead of physically deleting cache file...
1026
                                            if (trace) { trace("removing cache for updated file {0}", entryCache.getAbsolutePath()); } // NOI18N
1027
                                            entryCache.delete(); // TODO: We must just mark it as invalid instead of physically deleting cache file...
1028
                                        }
1026
                                    }
1029
                                    }
1027
                                } 
1030
                                } 
1028
1031
1029
                            } 
1032
                            } 
1030
                            if (!equals(newEntry.getLinkTarget(), oldEntry.getLinkTarget())) {
1033
                            if (!equals(newEntry.getLinkTarget(), oldEntry.getLinkTarget())) {
1031
                                changed = fire = true; // TODO: we forgot old link path, probably should be passed to change event 
1034
                                changed = fire = true; // TODO: we forgot old link path, probably should be passed to change event 
1032
                                getFileSystem().getFactory().setLink(this, getPath() + '/' + newEntry.getName(), newEntry.getLinkTarget());
1035
                                getFileSystem().getFactory().setLink(this, getAbsolutePath(newEntry), newEntry.getLinkTarget());
1033
                            } 
1036
                            } 
1034
                            if (!newEntry.getAccessAsString().equals(oldEntry.getAccessAsString())) {
1037
                            if (!newEntry.getAccessAsString().equals(oldEntry.getAccessAsString())) {
1035
                                changed = fire = true;
1038
                                changed = fire = true;
Lines 1142-1148 Link Here
1142
                    fireRemoteFileObjectCreated(fo);
1145
                    fireRemoteFileObjectCreated(fo);
1143
                }
1146
                }
1144
                for (DirEntry entry : entriesToFireChanged) {
1147
                for (DirEntry entry : entriesToFireChanged) {
1145
                    RemoteFileObjectBase fo = getFileSystem().getFactory().getCachedFileObject(getPath() + '/' + entry.getName());
1148
                    RemoteFileObjectBase fo = getFileSystem().getFactory().getCachedFileObject(getAbsolutePath(entry));
1146
                    if (fo != null) {
1149
                    if (fo != null) {
1147
                        if (fo.isPendingRemoteDelivery()) {
1150
                        if (fo.isPendingRemoteDelivery()) {
1148
                            RemoteLogger.getInstance().log(Level.FINE, "Skipping change event for pending file {0}", fo);
1151
                            RemoteLogger.getInstance().log(Level.FINE, "Skipping change event for pending file {0}", fo);
Lines 1153-1159 Link Here
1153
                    }
1156
                    }
1154
                }
1157
                }
1155
                for (DirEntry entry : entriesToFireChangedRO) {
1158
                for (DirEntry entry : entriesToFireChangedRO) {
1156
                    RemoteFileObjectBase fo = getFileSystem().getFactory().getCachedFileObject(getPath() + '/' + entry.getName());
1159
                    RemoteFileObjectBase fo = getFileSystem().getFactory().getCachedFileObject(getAbsolutePath(entry));
1157
                    if (fo != null) {
1160
                    if (fo != null) {
1158
                        if (fo.isPendingRemoteDelivery()) {
1161
                        if (fo.isPendingRemoteDelivery()) {
1159
                            RemoteLogger.getInstance().log(Level.FINE, "Skipping change event for pending file {0}", fo);
1162
                            RemoteLogger.getInstance().log(Level.FINE, "Skipping change event for pending file {0}", fo);
Lines 1169-1175 Link Here
1169
        }
1172
        }
1170
        return storage;
1173
        return storage;
1171
    }
1174
    }
1172
    
1175
1176
    private String getAbsolutePath(DirEntry oldEntry) {
1177
        return getPath() + '/' + oldEntry.getName(); //NOI18N
1178
    }
1179
1173
    private void fireDeletedEvent(RemoteFileObject parent, RemoteFileObject fo, FilesystemInterceptorProvider.FilesystemInterceptor interceptor, boolean expected) {
1180
    private void fireDeletedEvent(RemoteFileObject parent, RemoteFileObject fo, FilesystemInterceptorProvider.FilesystemInterceptor interceptor, boolean expected) {
1174
        if (interceptor != null) {
1181
        if (interceptor != null) {
1175
            interceptor.deletedExternally(FilesystemInterceptorProvider.toFileProxy(fo));
1182
            interceptor.deletedExternally(FilesystemInterceptorProvider.toFileProxy(fo));
Lines 1292-1298 Link Here
1292
    }
1299
    }
1293
1300
1294
    private RemoteFileObject invalidate(DirEntry oldEntry) {
1301
    private RemoteFileObject invalidate(DirEntry oldEntry) {
1295
        RemoteFileObject fo = getFileSystem().getFactory().invalidate(getPath() + '/' + oldEntry.getName());
1302
        RemoteFileObject fo = getFileSystem().getFactory().invalidate(getAbsolutePath(oldEntry));
1296
        File oldEntryCache = new File(getCache(), oldEntry.getCache());
1303
        File oldEntryCache = new File(getCache(), oldEntry.getCache());
1297
        removeFile(oldEntryCache);
1304
        removeFile(oldEntryCache);
1298
        return fo;
1305
        return fo;
(-)a/dlight.remote.impl/src/org/netbeans/modules/remote/impl/fs/RemoteFileObjectBase.java (-9 / +4 lines)
Lines 100-107 Link Here
100
100
101
    private static final byte MASK_VALID = 1;
101
    private static final byte MASK_VALID = 1;
102
    private static final byte CHECK_CAN_WRITE = 2;
102
    private static final byte CHECK_CAN_WRITE = 2;
103
    private static final byte BEING_UPLOADED = 4;
103
    protected static final byte CONNECTION_ISSUES = 4;
104
    protected static final byte CONNECTION_ISSUES = 8;
105
    
104
    
106
    protected RemoteFileObjectBase(RemoteFileObject wrapper, RemoteFileSystem fileSystem, ExecutionEnvironment execEnv,
105
    protected RemoteFileObjectBase(RemoteFileObject wrapper, RemoteFileSystem fileSystem, ExecutionEnvironment execEnv,
107
            RemoteFileObjectBase parent, String remotePath, File cache) {
106
            RemoteFileObjectBase parent, String remotePath, File cache) {
Lines 169-183 Link Here
169
            flags &= ~mask;
168
            flags &= ~mask;
170
        }
169
        }
171
    }
170
    }
172
    
171
173
    /*package*/ boolean isPendingRemoteDelivery() {
172
    /*package*/ boolean isPendingRemoteDelivery() {
174
        return getFlag(BEING_UPLOADED);
173
        return false;
175
    }
174
    }
176
    
175
177
    /*package*/ void setPendingRemoteDelivery(boolean value) {
178
        setFlag(BEING_UPLOADED, value);
179
    }
180
    
181
    public ExecutionEnvironment getExecutionEnvironment() {
176
    public ExecutionEnvironment getExecutionEnvironment() {
182
        return fileSystem.getExecutionEnvironment();
177
        return fileSystem.getExecutionEnvironment();
183
    }
178
    }
(-)a/dlight.remote.impl/src/org/netbeans/modules/remote/impl/fs/RemoteFileSystem.java (-3 / +11 lines)
Lines 122-134 Link Here
122
            new ArrayList<FileSystemProblemListener>();
122
            new ArrayList<FileSystemProblemListener>();
123
    transient private final StatusImpl status = new StatusImpl();
123
    transient private final StatusImpl status = new StatusImpl();
124
    private final LinkedHashSet<String> deleteOnExitFiles = new LinkedHashSet<String>();
124
    private final LinkedHashSet<String> deleteOnExitFiles = new LinkedHashSet<String>();
125
    private final PendingUploadsManager pendingUploadsManager;
125
126
126
    /*package*/ RemoteFileSystem(ExecutionEnvironment execEnv) throws IOException {
127
    /*package*/ RemoteFileSystem(ExecutionEnvironment execEnv) throws IOException {
127
        RemoteLogger.assertTrue(execEnv.isRemote());
128
        RemoteLogger.assertTrue(execEnv.isRemote());
128
        this.execEnv = execEnv;
129
        this.execEnv = execEnv;
129
        this.remoteFileSupport = new RemoteFileSupport();
130
        this.remoteFileSupport = new RemoteFileSupport();
130
        factory = new RemoteFileObjectFactory(this);
131
        factory = new RemoteFileObjectFactory(this);
131
        refreshManager = new RefreshManager(execEnv, factory);
132
        // FIXUP: it's better than asking a compiler instance... but still a fixup.
132
        // FIXUP: it's better than asking a compiler instance... but still a fixup.
133
        // Should be moved to a proper place
133
        // Should be moved to a proper place
134
        this.filePrefix = FileSystemCacheProvider.getCacheRoot(execEnv);
134
        this.filePrefix = FileSystemCacheProvider.getCacheRoot(execEnv);
Lines 136-145 Link Here
136
            throw new IllegalStateException("Can not find cache root for remote file system at " + execEnv); //NOI18N
136
            throw new IllegalStateException("Can not find cache root for remote file system at " + execEnv); //NOI18N
137
        }
137
        }
138
        cache = new File(filePrefix);
138
        cache = new File(filePrefix);
139
        root = new RemoteFileObject(this);
140
        rootDelegate = new RootFileObject(root, this, execEnv, cache); // NOI18N
141
        pendingUploadsManager = new PendingUploadsManager(factory, rootDelegate, new File(getCache(), ".rfs_pending"));
142
        pendingUploadsManager.load();
143
        refreshManager = new RefreshManager(execEnv, factory, pendingUploadsManager);
139
        if (!cache.exists() && !cache.mkdirs()) {
144
        if (!cache.exists() && !cache.mkdirs()) {
140
            throw new IOException(NbBundle.getMessage(getClass(), "ERR_CreateDir", cache.getAbsolutePath()));
145
            throw new IOException(NbBundle.getMessage(getClass(), "ERR_CreateDir", cache.getAbsolutePath()));
141
        }
146
        }
142
        this.rootDelegate = new RootFileObject(this.root = new RemoteFileObject(this), this, execEnv, cache); // NOI18N
143
147
144
        final WindowFocusListener windowFocusListener = new WindowFocusListener() {
148
        final WindowFocusListener windowFocusListener = new WindowFocusListener() {
145
149
Lines 193-199 Link Here
193
        }
197
        }
194
        if (ATTR_STATS) { dumpAttrStat(); }
198
        if (ATTR_STATS) { dumpAttrStat(); }
195
    }
199
    }
196
    
200
201
    public PendingUploadsManager getPendingUploadsManager() {
202
        return pendingUploadsManager;
203
    }
204
197
    /*package*/ ExecutionEnvironment getExecutionEnvironment() {
205
    /*package*/ ExecutionEnvironment getExecutionEnvironment() {
198
        return execEnv;
206
        return execEnv;
199
    }
207
    }
(-)a/dlight.remote.impl/src/org/netbeans/modules/remote/impl/fs/RemotePlainFile.java (-40 / +140 lines)
Lines 49-55 Link Here
49
import java.io.IOException;
49
import java.io.IOException;
50
import java.io.InputStream;
50
import java.io.InputStream;
51
import java.io.OutputStream;
51
import java.io.OutputStream;
52
import java.lang.ref.SoftReference;
53
import java.net.ConnectException;
52
import java.net.ConnectException;
54
import java.util.Set;
53
import java.util.Set;
55
import java.util.StringTokenizer;
54
import java.util.StringTokenizer;
Lines 58-63 Link Here
58
import java.util.concurrent.Future;
57
import java.util.concurrent.Future;
59
import java.util.concurrent.TimeUnit;
58
import java.util.concurrent.TimeUnit;
60
import java.util.concurrent.locks.Condition;
59
import java.util.concurrent.locks.Condition;
60
import java.util.concurrent.locks.Lock;
61
import java.util.concurrent.locks.ReentrantLock;
61
import java.util.concurrent.locks.ReentrantLock;
62
import java.util.logging.Level;
62
import java.util.logging.Level;
63
import org.netbeans.modules.dlight.libs.common.DLightLibsCommonLogger;
63
import org.netbeans.modules.dlight.libs.common.DLightLibsCommonLogger;
Lines 72-77 Link Here
72
import org.openide.filesystems.FileEvent;
72
import org.openide.filesystems.FileEvent;
73
import org.openide.filesystems.FileLock;
73
import org.openide.filesystems.FileLock;
74
import org.openide.filesystems.FileObject;
74
import org.openide.filesystems.FileObject;
75
import org.openide.util.Exceptions;
75
76
76
/**
77
/**
77
 *
78
 *
Lines 79-94 Link Here
79
 */
80
 */
80
public final class RemotePlainFile extends RemoteFileObjectBase {
81
public final class RemotePlainFile extends RemoteFileObjectBase {
81
82
83
    public static enum UploadState {
84
        OK,
85
        UPLOADING,
86
        FAILED
87
    }
88
82
    private static final int LOCK_TIMEOUT = Integer.getInteger("remote.rwlock.timeout", 4); // NOI18N
89
    private static final int LOCK_TIMEOUT = Integer.getInteger("remote.rwlock.timeout", 4); // NOI18N
83
    
90
84
    private final char fileTypeChar;
91
    private final char fileTypeChar;
85
//    private SoftReference<CachedRemoteInputStream> fileContentCache = new SoftReference<CachedRemoteInputStream>(null);
92
//    private SoftReference<CachedRemoteInputStream> fileContentCache = new SoftReference<CachedRemoteInputStream>(null);
86
    private SimpleRWLock rwl = new SimpleRWLock();
93
    private SimpleRWLock rwl = new SimpleRWLock();
94
95
    private final Object uploadStateLock = new Object();
96
97
    /** guarded by uploadStateLock */
98
    private UploadState uploadState;
99
100
    /** guarded by RemoteFileSystem.getLock(getCache()) */
101
    private long lastUploadTimestamp = -1;
87
    
102
    
88
    /*package*/ RemotePlainFile(RemoteFileObject wrapper, RemoteFileSystem fileSystem, ExecutionEnvironment execEnv, 
103
    /*package*/ RemotePlainFile(RemoteFileObject wrapper, RemoteFileSystem fileSystem, ExecutionEnvironment execEnv, 
89
            RemoteDirectory parent, String remotePath, File cache, FileType fileType) {
104
            RemoteDirectory parent, String remotePath, File cache, FileType fileType) {
90
        super(wrapper, fileSystem, execEnv, parent, remotePath, cache);
105
        super(wrapper, fileSystem, execEnv, parent, remotePath, cache);
91
        fileTypeChar = fileType.toChar(); // TODO: pass when created
106
        fileTypeChar = fileType.toChar(); // TODO: pass when created
107
        changeUploadState(
108
                fileSystem.getPendingUploadsManager().isPendingOrFailedUpload(remotePath) ?
109
                UploadState.FAILED : UploadState.OK);
92
    }
110
    }
93
111
94
    @Override
112
    @Override
Lines 444-449 Link Here
444
    // Fixing #206726 - If a remote file is saved frequently, "File modified externally" message appears, user changes are lost
462
    // Fixing #206726 - If a remote file is saved frequently, "File modified externally" message appears, user changes are lost
445
    @Override
463
    @Override
446
    protected void refreshImpl(boolean recursive, Set<String> antiLoop, boolean expected) throws ConnectException, IOException, InterruptedException, CancellationException, ExecutionException {
464
    protected void refreshImpl(boolean recursive, Set<String> antiLoop, boolean expected) throws ConnectException, IOException, InterruptedException, CancellationException, ExecutionException {
465
        if (fixUpload()) {
466
            return;
467
        }
447
        if (Boolean.getBoolean("cnd.remote.refresh.plain.file")) { //NOI18N
468
        if (Boolean.getBoolean("cnd.remote.refresh.plain.file")) { //NOI18N
448
            long time = System.currentTimeMillis();
469
            long time = System.currentTimeMillis();
449
            getParent().refreshImpl(false, antiLoop, expected);
470
            getParent().refreshImpl(false, antiLoop, expected);
Lines 451-461 Link Here
451
        }
472
        }
452
    }
473
    }
453
474
475
    /*package*/ boolean fixUpload() {
476
        boolean fixUpload = false;
477
        if (ConnectionManager.getInstance().isConnectedTo(getExecutionEnvironment())) {
478
            synchronized (uploadStateLock) {
479
                fixUpload = (uploadState == UploadState.FAILED);
480
            }
481
            if (fixUpload) {
482
                try {
483
                    upload();
484
                } catch (IOException ex) {
485
                    ex.printStackTrace();
486
                }
487
            }
488
        }
489
        return fixUpload;
490
    }
491
454
    @Override
492
    @Override
455
    public FileType getType() {
493
    public FileType getType() {
456
        return FileType.fromChar(fileTypeChar);
494
        return FileType.fromChar(fileTypeChar);
457
    }
495
    }
458
496
497
    public UploadState getUploadState() {
498
        synchronized (uploadStateLock) {
499
            return uploadState;
500
        }
501
    }
502
503
    private UploadState changeUploadState(UploadState newState) {
504
        return changeUploadState(null, newState);
505
    }
506
507
    private UploadState changeUploadState(UploadState from, UploadState to) {
508
        synchronized (uploadStateLock) {
509
            if (from != null && from != uploadState) {
510
                return null;
511
            }
512
            UploadState prevState = uploadState;
513
            uploadState = to;
514
            switch (to) {
515
                case OK:
516
                    getFileSystem().getPendingUploadsManager().removePendingOrFailedUpload(this);
517
                    break;
518
                case UPLOADING:
519
                    getFileSystem().getPendingUploadsManager().addPendingUpload(this);
520
                    break;
521
                case FAILED:
522
                    getFileSystem().getPendingUploadsManager().addFailedUpload(this);
523
                    break;
524
                default:
525
                    Exceptions.printStackTrace(new IllegalStateException(
526
                            "Unexpected " + UploadState.class.getSimpleName() + ": " + to)); //NOI18N
527
            }
528
            return prevState;
529
        }
530
    }
531
532
    @Override
533
    /*package*/ boolean isPendingRemoteDelivery() {
534
        synchronized (uploadStateLock) {
535
            return uploadState == UploadState.UPLOADING || uploadState == UploadState.FAILED;
536
        }
537
    }
538
459
    private static class DelegateOutputStream extends OutputStream {
539
    private static class DelegateOutputStream extends OutputStream {
460
540
461
        private final FileOutputStream delegate;
541
        private final FileOutputStream delegate;
Lines 487-539 Link Here
487
            }
567
            }
488
            try {
568
            try {
489
                delegate.close();
569
                delegate.close();
490
                file.setPendingRemoteDelivery(true);
570
                file.upload();
491
                CommonTasksSupport.UploadParameters params = new CommonTasksSupport.UploadParameters(
492
                        file.getCache(), file.getExecutionEnvironment(), file.getPath(), -1, false, null);
493
                Future<UploadStatus> task = CommonTasksSupport.uploadFile(params);
494
                try {
495
                    UploadStatus uploadStatus = task.get();
496
                    if (uploadStatus.isOK()) {
497
                        RemoteLogger.getInstance().log(Level.FINEST, "WritingQueue: uploading {0} succeeded", this);
498
                        file.getParent().updateStat(file, uploadStatus.getStatInfo());
499
                        FileEvent ev = new FileEvent(file.getOwnerFileObject(), file.getOwnerFileObject(), true, uploadStatus.getStatInfo().getLastModified().getTime());
500
                        file.getOwnerFileObject().fireFileChangedEvent(file.getListenersWithParent(), ev);
501
                    } else {
502
                        RemoteLogger.getInstance().log(Level.FINEST, "WritingQueue: uploading {0} failed", this);
503
                        file.setPendingRemoteDelivery(false);
504
                        throw new IOException(uploadStatus.getError() + " " + uploadStatus.getExitCode()); //NOI18N
505
                    }
506
                } catch (InterruptedException ex) {
507
                    throw newIOException(ex);
508
                } catch (ExecutionException ex) {
509
                    //Exceptions.printStackTrace(ex); // should never be the case - the task is done
510
                    if (!ConnectionManager.getInstance().isConnectedTo(file.getExecutionEnvironment())) {
511
                        file.getFileSystem().addPendingFile(file);
512
                        throw new ConnectException(ex.getMessage());
513
                    } else {
514
                        if (RemoteFileSystemUtils.isFileNotFoundException(ex)) {
515
                            throw new FileNotFoundException(file.getPath());
516
                        } else if (ex.getCause() instanceof IOException) {
517
                            throw (IOException) ex.getCause();
518
                        } else {
519
                            throw newIOException(ex);
520
                        }
521
                    }
522
                }
523
                closed = true;
571
                closed = true;
524
            } finally {
572
            } finally {
525
                file.rwl.writeUnlock();
573
                file.rwl.writeUnlock();
526
            }
574
            }
527
        }
575
        }
528
576
529
        private IOException newIOException(Exception cause) {
530
            return new IOException("Error uploading " + file.getPath() + " to " + file.getExecutionEnvironment() + ':' + //NOI18N
531
                    cause.getMessage(), cause);
532
        }
533
534
        @Override
577
        @Override
535
        public void flush() throws IOException {
578
        public void flush() throws IOException {
536
            delegate.flush();
579
            delegate.flush();
537
        }
580
        }
538
    }
581
    }
582
583
    private void upload() throws IOException {
584
585
        Lock writeLock = RemoteFileSystem.getLock(getCache()).writeLock();
586
        writeLock.lock();
587
        try {
588
            long cacheTimestamp = getCache().lastModified();
589
            UploadState us = getUploadState();
590
            if (us == UploadState.OK && cacheTimestamp == lastUploadTimestamp) {
591
                return;
592
            }
593
            lastUploadTimestamp = -1;
594
            changeUploadState(UploadState.UPLOADING);
595
            CommonTasksSupport.UploadParameters params = new CommonTasksSupport.UploadParameters(
596
                    getCache(), getExecutionEnvironment(), getPath(), -1, false, null);
597
            Future<UploadStatus> task = CommonTasksSupport.uploadFile(params);
598
            try {
599
                UploadStatus uploadStatus = task.get();
600
                if (uploadStatus.isOK()) {
601
                    RemoteLogger.getInstance().log(Level.FINEST, "WritingQueue: uploading {0} succeeded", this);
602
                    getParent().updateStat(this, uploadStatus.getStatInfo());
603
                    changeUploadState(UploadState.OK);
604
                    lastUploadTimestamp = cacheTimestamp;
605
                    FileEvent ev = new FileEvent(getOwnerFileObject(), getOwnerFileObject(), true, uploadStatus.getStatInfo().getLastModified().getTime());
606
                    getOwnerFileObject().fireFileChangedEvent(getListenersWithParent(), ev);
607
                } else {
608
                    RemoteLogger.getInstance().log(Level.FINEST, "WritingQueue: uploading {0} failed", this);
609
                    throw new IOException(uploadStatus.getError() + " " + uploadStatus.getExitCode()); //NOI18N
610
                }
611
            } catch (InterruptedException ex) {
612
                throw newIOException(this, ex);
613
            } catch (ExecutionException ex) {
614
                //Exceptions.printStackTrace(ex); // should never be the case - the task is done
615
                if (!ConnectionManager.getInstance().isConnectedTo(getExecutionEnvironment())) {
616
                    getFileSystem().addPendingFile(this);
617
                    throw new ConnectException(ex.getMessage());
618
                } else {
619
                    if (RemoteFileSystemUtils.isFileNotFoundException(ex)) {
620
                        throw new FileNotFoundException(getPath());
621
                    } else if (ex.getCause() instanceof IOException) {
622
                        throw (IOException) ex.getCause();
623
                    } else {
624
                        throw newIOException(this, ex);
625
                    }
626
                }
627
            } finally {
628
                changeUploadState(UploadState.UPLOADING, UploadState.FAILED);
629
            }
630
        } finally {
631
            writeLock.unlock();
632
        }
633
    }
634
635
    private IOException newIOException(RemotePlainFile file, Exception cause) {
636
        return new IOException("Error uploading " + file.getPath() + " to " + file.getExecutionEnvironment() + ':' + //NOI18N
637
                cause.getMessage(), cause);
638
    }
539
}
639
}

Return to bug 227936