Lines 45-50
Link Here
|
45 |
import java.io.BufferedOutputStream; |
45 |
import java.io.BufferedOutputStream; |
46 |
import java.io.ByteArrayInputStream; |
46 |
import java.io.ByteArrayInputStream; |
47 |
import java.io.DataInput; |
47 |
import java.io.DataInput; |
|
|
48 |
import java.io.DataInputStream; |
48 |
import java.io.DataOutput; |
49 |
import java.io.DataOutput; |
49 |
import java.io.DataOutputStream; |
50 |
import java.io.DataOutputStream; |
50 |
import java.io.File; |
51 |
import java.io.File; |
Lines 68-74
Link Here
|
68 |
import java.util.Locale; |
69 |
import java.util.Locale; |
69 |
import java.util.Random; |
70 |
import java.util.Random; |
70 |
import java.util.Set; |
71 |
import java.util.Set; |
71 |
import java.util.StringTokenizer; |
|
|
72 |
import java.util.concurrent.atomic.AtomicInteger; |
72 |
import java.util.concurrent.atomic.AtomicInteger; |
73 |
import java.util.concurrent.atomic.AtomicLong; |
73 |
import java.util.concurrent.atomic.AtomicLong; |
74 |
import java.util.concurrent.atomic.AtomicReference; |
74 |
import java.util.concurrent.atomic.AtomicReference; |
Lines 91-99
Link Here
|
91 |
private static final Logger LOG = Logger.getLogger(Stamps.class.getName()); |
91 |
private static final Logger LOG = Logger.getLogger(Stamps.class.getName()); |
92 |
private static AtomicLong moduleJARs; |
92 |
private static AtomicLong moduleJARs; |
93 |
private static File moduleNewestFile; |
93 |
private static File moduleNewestFile; |
94 |
private static String[] dirs; |
|
|
95 |
private static File[] fallbackCache; |
94 |
private static File[] fallbackCache; |
96 |
private static boolean populated; |
95 |
private static boolean populated; |
|
|
96 |
private static Boolean clustersChanged; |
97 |
|
97 |
|
98 |
private Worker worker = new Worker(); |
98 |
private Worker worker = new Worker(); |
99 |
|
99 |
|
Lines 107-127
Link Here
|
107 |
static void main(String... args) { |
107 |
static void main(String... args) { |
108 |
if (args.length == 1 && "reset".equals(args[0])) { // NOI18N |
108 |
if (args.length == 1 && "reset".equals(args[0])) { // NOI18N |
109 |
moduleJARs = null; |
109 |
moduleJARs = null; |
110 |
dirs = null; |
110 |
Clusters.clear(); |
|
|
111 |
clustersChanged = null; |
111 |
fallbackCache = null; |
112 |
fallbackCache = null; |
112 |
stamp(false); |
113 |
stamp(false); |
113 |
return; |
114 |
return; |
114 |
} |
115 |
} |
115 |
if (args.length == 1 && "init".equals(args[0])) { // NOI18N |
116 |
if (args.length == 1 && "init".equals(args[0])) { // NOI18N |
116 |
moduleJARs = null; |
117 |
moduleJARs = null; |
117 |
dirs = null; |
118 |
Clusters.clear(); |
|
|
119 |
clustersChanged = null; |
118 |
fallbackCache = null; |
120 |
fallbackCache = null; |
119 |
stamp(true); |
121 |
stamp(true); |
120 |
return; |
122 |
return; |
121 |
} |
123 |
} |
122 |
if (args.length == 1 && "clear".equals(args[0])) { // NOI18N |
124 |
if (args.length == 1 && "clear".equals(args[0])) { // NOI18N |
123 |
moduleJARs = null; |
125 |
moduleJARs = null; |
124 |
dirs = null; |
126 |
Clusters.clear(); |
|
|
127 |
clustersChanged = null; |
125 |
fallbackCache = null; |
128 |
fallbackCache = null; |
126 |
return; |
129 |
return; |
127 |
} |
130 |
} |
Lines 183-188
Link Here
|
183 |
return asByteBuffer(cache, true, false); |
186 |
return asByteBuffer(cache, true, false); |
184 |
} |
187 |
} |
185 |
final File file(String cache, int[] len) { |
188 |
final File file(String cache, int[] len) { |
|
|
189 |
if (clustersChanged()) { |
190 |
return null; |
191 |
} |
192 |
|
186 |
checkPopulateCache(); |
193 |
checkPopulateCache(); |
187 |
|
194 |
|
188 |
synchronized (this) { |
195 |
synchronized (this) { |
Lines 191-224
Link Here
|
191 |
return null; |
198 |
return null; |
192 |
} |
199 |
} |
193 |
} |
200 |
} |
194 |
|
201 |
return fileImpl(cache, len, moduleJARs()); |
195 |
File cacheFile = Places.getCacheSubfile(cache); |
|
|
196 |
long last = cacheFile.lastModified(); |
197 |
if (last <= 0) { |
198 |
LOG.log(Level.FINE, "Cache does not exist when asking for {0}", cache); // NOI18N |
199 |
cacheFile = findFallbackCache(cache); |
200 |
if (cacheFile == null || (last = cacheFile.lastModified()) <= 0) { |
201 |
return null; |
202 |
} |
203 |
LOG.log(Level.FINE, "Found fallback cache at {0}", cacheFile); |
204 |
} |
205 |
|
206 |
if (moduleJARs() > last) { |
207 |
LOG.log(Level.FINE, "Timestamp does not pass when asking for {0}. Newest file {1}", new Object[] { cache, moduleNewestFile }); // NOI18N |
208 |
return null; |
209 |
} |
210 |
|
211 |
long longLen = cacheFile.length(); |
212 |
if (longLen > Integer.MAX_VALUE) { |
213 |
LOG.warning("Cache file is too big: " + longLen + " bytes for " + cacheFile); // NOI18N |
214 |
return null; |
215 |
} |
216 |
if (len != null) { |
217 |
len[0] = (int)longLen; |
218 |
} |
219 |
|
220 |
LOG.log(Level.FINE, "Cache found: {0}", cache); // NOI18N |
221 |
return cacheFile; |
222 |
} |
202 |
} |
223 |
|
203 |
|
224 |
private ByteBuffer asByteBuffer(String cache, boolean direct, boolean mmap) { |
204 |
private ByteBuffer asByteBuffer(String cache, boolean direct, boolean mmap) { |
Lines 260-271
Link Here
|
260 |
*/ |
240 |
*/ |
261 |
public void scheduleSave(Updater updater, String cache, boolean append) { |
241 |
public void scheduleSave(Updater updater, String cache, boolean append) { |
262 |
boolean firstAdd; |
242 |
boolean firstAdd; |
263 |
synchronized (worker) { |
243 |
firstAdd = scheduleSaveImpl(updater, cache, append); |
264 |
firstAdd = worker.addStorage(new Store(updater, cache, append)); |
|
|
265 |
} |
266 |
LOG.log(firstAdd ? Level.FINE : Level.FINER, |
244 |
LOG.log(firstAdd ? Level.FINE : Level.FINER, |
267 |
"Scheduling save for {0} cache", cache |
245 |
"Scheduling save for {0} cache", cache |
268 |
); |
246 |
); |
|
|
247 |
Clusters.scheduleSave(this); |
248 |
} |
249 |
|
250 |
final boolean scheduleSaveImpl(Updater updater, String cache, boolean append) { |
251 |
synchronized (worker) { |
252 |
return worker.addStorage(new Store(updater, cache, append)); |
253 |
} |
269 |
} |
254 |
} |
270 |
|
255 |
|
271 |
/** Flushes all caches. |
256 |
/** Flushes all caches. |
Lines 345-380
Link Here
|
345 |
stamp(checkStampFile, result, newestFile); |
330 |
stamp(checkStampFile, result, newestFile); |
346 |
return result; |
331 |
return result; |
347 |
} |
332 |
} |
348 |
|
|
|
349 |
private static synchronized String[] dirs() { |
350 |
if (dirs == null) { |
351 |
List<String> tmp = new ArrayList<String>(); |
352 |
String nbdirs = System.getProperty("netbeans.dirs"); // NOI18N |
353 |
if (nbdirs != null) { |
354 |
StringTokenizer tok = new StringTokenizer(nbdirs, File.pathSeparator); |
355 |
while (tok.hasMoreTokens()) { |
356 |
tmp.add(tok.nextToken()); |
357 |
} |
358 |
} |
359 |
dirs = tmp.toArray(new String[tmp.size()]); |
360 |
} |
361 |
return dirs; |
362 |
} |
363 |
|
333 |
|
364 |
private static void stamp(boolean checkStampFile, AtomicLong result, AtomicReference<File> newestFile) { |
334 |
private static void stamp(boolean checkStampFile, AtomicLong result, AtomicReference<File> newestFile) { |
365 |
StringBuilder sb = new StringBuilder(); |
335 |
StringBuilder sb = new StringBuilder(); |
366 |
|
336 |
|
367 |
Set<File> processedDirs = new HashSet<File>(); |
337 |
Set<File> processedDirs = new HashSet<File>(); |
|
|
338 |
String[] relativeDirs = Clusters.relativeDirsWithHome(); |
368 |
String home = System.getProperty ("netbeans.home"); // NOI18N |
339 |
String home = System.getProperty ("netbeans.home"); // NOI18N |
369 |
if (home != null) { |
340 |
if (home != null) { |
370 |
long stamp = stampForCluster (new File (home), result, newestFile, processedDirs, checkStampFile, true, null); |
341 |
long stamp = stampForCluster (new File (home), result, newestFile, processedDirs, checkStampFile, true, null); |
371 |
sb.append("home=").append(stamp).append('\n'); |
342 |
sb.append(relativeDirs[0]).append('=').append(stamp).append('\n'); |
372 |
} |
343 |
} |
373 |
for (String t : dirs()) { |
344 |
String[] drs = Clusters.dirs(); |
374 |
final File clusterDir = new File(t); |
345 |
for (int i = 0; i < drs.length; i++) { |
|
|
346 |
final File clusterDir = new File(drs[i]); |
375 |
long stamp = stampForCluster(clusterDir, result, newestFile, processedDirs, checkStampFile, true, null); |
347 |
long stamp = stampForCluster(clusterDir, result, newestFile, processedDirs, checkStampFile, true, null); |
376 |
if (stamp != -1) { |
348 |
if (stamp != -1) { |
377 |
sb.append(clusterDir.getName()).append('=').append(stamp).append('\n'); |
349 |
sb.append("cluster.").append(relativeDirs[i + 1]).append('=').append(stamp).append('\n'); |
378 |
} |
350 |
} |
379 |
} |
351 |
} |
380 |
File user = Places.getUserDirectory(); |
352 |
File user = Places.getUserDirectory(); |
Lines 561-568
Link Here
|
561 |
private static File findFallbackCache(String cache) { |
533 |
private static File findFallbackCache(String cache) { |
562 |
if (fallbackCache == null) { |
534 |
if (fallbackCache == null) { |
563 |
fallbackCache = new File[0]; |
535 |
fallbackCache = new File[0]; |
564 |
if (dirs().length >= 1) { |
536 |
if (Clusters.dirs().length >= 1) { |
565 |
File fallback = new File(new File(new File(dirs()[0]), "var"), "cache"); // NOI18N |
537 |
File fallback = new File(new File(new File(Clusters.dirs()[0]), "var"), "cache"); // NOI18N |
566 |
if (fallback.isDirectory()) { |
538 |
if (fallback.isDirectory()) { |
567 |
fallbackCache = new File[]{ fallback }; |
539 |
fallbackCache = new File[]{ fallback }; |
568 |
} |
540 |
} |
Lines 620-625
Link Here
|
620 |
LOG.log(Level.INFO, "Failed to populate {0}", cache); |
592 |
LOG.log(Level.INFO, "Failed to populate {0}", cache); |
621 |
} |
593 |
} |
622 |
} |
594 |
} |
|
|
595 |
|
596 |
private static boolean clustersChanged() { |
597 |
if (clustersChanged != null) { |
598 |
return clustersChanged; |
599 |
} |
600 |
|
601 |
final String clustersCache = "all-clusters.dat"; // NOI18N |
602 |
File f = fileImpl(clustersCache, null, -1); // no timestamp check |
603 |
if (f != null) { |
604 |
DataInputStream dis = null; |
605 |
try { |
606 |
dis = new DataInputStream(new FileInputStream(f)); |
607 |
if (Clusters.compareDirs(dis)) { |
608 |
return false; |
609 |
} |
610 |
} catch (IOException ex) { |
611 |
return clustersChanged = true; |
612 |
} finally { |
613 |
if (dis != null) { |
614 |
try { |
615 |
dis.close(); |
616 |
} catch (IOException ex) { |
617 |
LOG.log(Level.INFO, null, ex); |
618 |
} |
619 |
} |
620 |
} |
621 |
} else { |
622 |
// missing cluster file signals caches are OK, for |
623 |
// backward compatibility |
624 |
return clustersChanged = false; |
625 |
} |
626 |
return clustersChanged = true; |
627 |
} |
628 |
|
629 |
private static File fileImpl(String cache, int[] len, long moduleJARs) { |
630 |
File cacheFile = Places.getCacheSubfile(cache); |
631 |
long last = cacheFile.lastModified(); |
632 |
if (last <= 0) { |
633 |
LOG.log(Level.FINE, "Cache does not exist when asking for {0}", cache); // NOI18N |
634 |
cacheFile = findFallbackCache(cache); |
635 |
if (cacheFile == null || (last = cacheFile.lastModified()) <= 0) { |
636 |
return null; |
637 |
} |
638 |
LOG.log(Level.FINE, "Found fallback cache at {0}", cacheFile); |
639 |
} |
640 |
|
641 |
if (moduleJARs > last) { |
642 |
LOG.log(Level.FINE, "Timestamp does not pass when asking for {0}. Newest file {1}", new Object[] { cache, moduleNewestFile }); // NOI18N |
643 |
return null; |
644 |
} |
645 |
|
646 |
long longLen = cacheFile.length(); |
647 |
if (longLen > Integer.MAX_VALUE) { |
648 |
LOG.log(Level.WARNING, "Cache file is too big: {0} bytes for {1}", new Object[]{longLen, cacheFile}); // NOI18N |
649 |
return null; |
650 |
} |
651 |
if (len != null) { |
652 |
len[0] = (int)longLen; |
653 |
} |
654 |
|
655 |
LOG.log(Level.FINE, "Cache found: {0}", cache); // NOI18N |
656 |
return cacheFile; |
657 |
} |
623 |
|
658 |
|
624 |
/** A callback interface to flush content of some cache at a suitable |
659 |
/** A callback interface to flush content of some cache at a suitable |
625 |
* point in time. |
660 |
* point in time. |
Lines 908-914
Link Here
|
908 |
return relative; |
943 |
return relative; |
909 |
} |
944 |
} |
910 |
int indx = Integer.parseInt(index); |
945 |
int indx = Integer.parseInt(index); |
911 |
String[] _dirs = dirs(); |
946 |
String[] _dirs = Clusters.dirs(); |
912 |
if (indx < 0 || indx >= _dirs.length) { |
947 |
if (indx < 0 || indx >= _dirs.length) { |
913 |
throw new IOException("Bad index " + indx + " for " + Arrays.toString(_dirs)); |
948 |
throw new IOException("Bad index " + indx + " for " + Arrays.toString(_dirs)); |
914 |
} |
949 |
} |
Lines 931-937
Link Here
|
931 |
return; |
966 |
return; |
932 |
} |
967 |
} |
933 |
int cnt = 0; |
968 |
int cnt = 0; |
934 |
for (String p : dirs()) { |
969 |
for (String p : Clusters.dirs()) { |
935 |
if (testWritePath(path, p, "" + cnt, out)) { |
970 |
if (testWritePath(path, p, "" + cnt, out)) { |
936 |
return; |
971 |
return; |
937 |
} |
972 |
} |