1 19 20 package org.netbeans.modules.subversion; 21 22 import org.netbeans.modules.subversion.util.*; 23 import org.netbeans.modules.turbo.TurboProvider; 24 import org.openide.filesystems.FileUtil; 25 import org.openide.filesystems.Repository; 26 import org.openide.ErrorManager; 27 28 import java.io.*; 29 import java.util.*; 30 31 36 class DiskMapTurboProvider implements TurboProvider { 37 38 static final String ATTR_STATUS_MAP = "subversion.STATUS_MAP"; 40 private static final int STATUS_VALUABLE = FileInformation.STATUS_MANAGED & ~FileInformation.STATUS_VERSIONED_UPTODATE; 41 private static final String CACHE_DIRECTORY = "svncache"; 43 private File cacheStore; 44 private int storeSerial; 45 46 private int cachedStoreSerial = -1; 47 private Map<File, FileInformation> cachedValues; 48 49 DiskMapTurboProvider() { 50 initCacheStore(); 51 } 52 53 synchronized Map<File, FileInformation> getAllModifiedValues() { 54 if (cachedStoreSerial != storeSerial || cachedValues == null) { 55 cachedValues = new HashMap<File, FileInformation>(); 56 File [] files = cacheStore.listFiles(); 57 for (int i = 0; i < files.length; i++) { 58 File file = files[i]; 59 if (file.getName().endsWith(".bin") == false) { continue; 62 } 63 DataInputStream dis = null; 64 try { 65 int retry = 0; 66 while (true) { 67 try { 68 dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); 69 break; 70 } catch (IOException ioex) { 71 retry++; 72 if (retry > 7) { 73 throw ioex; 74 } 75 Thread.sleep(retry * 30); 76 } 77 } 78 79 for (;;) { 80 int pathLen = dis.readInt(); 81 dis.readInt(); 82 String path = readChars(dis, pathLen); 83 Map value = readValue(dis, path); 84 for (Iterator j = value.keySet().iterator(); j.hasNext();) { 85 File f = (File) j.next(); 86 FileInformation info = (FileInformation) value.get(f); 87 if ((info.getStatus() & STATUS_VALUABLE) != 0) { 88 cachedValues.put(f, info); 89 } 90 } 91 } 92 } catch (EOFException e) { 93 } catch (Exception e) { 95 ErrorManager.getDefault().notify(e); 96 } finally { 97 if (dis != null) try { dis.close(); } catch (IOException e) {} 98 } 99 } 100 cachedStoreSerial = storeSerial; 101 cachedValues = Collections.unmodifiableMap(cachedValues); 102 } 103 return cachedValues; 104 } 105 106 public boolean recognizesAttribute(String name) { 107 return ATTR_STATUS_MAP.equals(name); 108 } 109 110 public boolean recognizesEntity(Object key) { 111 return key instanceof File; 112 } 113 114 public synchronized Object readEntry(Object key, String name, MemoryCache memoryCache) { 115 assert key instanceof File; 116 assert name != null; 117 118 boolean readFailed = false; 119 File dir = (File) key; 120 File store = getStore(dir); 121 if (!store.isFile()) { 122 return null; 123 } 124 125 String dirPath = dir.getAbsolutePath(); 126 int dirPathLen = dirPath.length(); 127 DataInputStream dis = null; 128 try { 129 130 int retry = 0; 131 while (true) { 132 try { 133 dis = new DataInputStream(new BufferedInputStream(new FileInputStream(store))); 134 break; 135 } catch (IOException ioex) { 136 retry++; 137 if (retry > 7) { 138 throw ioex; 139 } 140 Thread.sleep(retry * 30); 141 } 142 } 143 144 for (;;) { 145 int pathLen = dis.readInt(); 146 int mapLen = dis.readInt(); 147 if (pathLen != dirPathLen) { 148 skip(dis, pathLen * 2 + mapLen); 149 } else { 150 String path = readChars(dis, pathLen); 151 if (dirPath.equals(path)) { 152 return readValue(dis, path); 153 } else { 154 skip(dis, mapLen); 155 } 156 } 157 } 158 } catch (EOFException e) { 159 } catch (Exception e) { 161 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 162 readFailed = true; 163 } finally { 164 if (dis != null) try { dis.close(); } catch (IOException e) {} 165 } 166 if (readFailed) store.delete(); 167 return null; 168 } 169 170 public synchronized boolean writeEntry(Object key, String name, Object value) { 171 assert key instanceof File; 172 assert name != null; 173 174 if (value != null) { 175 if (!(value instanceof Map)) return false; 176 if (!isValuable(value)) value = null; 177 } 178 179 File dir = (File) key; 180 String dirPath = dir.getAbsolutePath(); 181 int dirPathLen = dirPath.length(); 182 File store = getStore(dir); 183 184 if (value == null && !store.exists()) return true; 185 186 File storeNew = new File(store.getParentFile(), store.getName() + ".new"); 188 DataOutputStream oos = null; 189 DataInputStream dis = null; 190 try { 191 oos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(storeNew))); 192 if (value != null) { 193 writeEntry(oos, dirPath, value); 194 } 195 if (store.exists()) { 196 int retry = 0; 197 while (true) { 198 try { 199 dis = new DataInputStream(new BufferedInputStream(new FileInputStream(store))); 200 break; 201 } catch (IOException ioex) { 202 retry++; 203 if (retry > 7) { 204 throw ioex; 205 } 206 Thread.sleep(retry * 30); 207 } 208 } 209 210 for (;;) { 211 int pathLen; 212 try { 213 pathLen = dis.readInt(); 214 } catch (EOFException e) { 215 break; 216 } 217 int mapLen = dis.readInt(); 218 if (pathLen == dirPathLen) { 219 String path = readChars(dis, pathLen); 220 if (dirPath.equals(path)) { 221 skip(dis, mapLen); 222 } else { 223 oos.writeInt(pathLen); 224 oos.writeInt(mapLen); 225 oos.writeChars(path); 226 copyStreams(oos, dis, mapLen); 227 } 228 } else { 229 oos.writeInt(pathLen); 230 oos.writeInt(mapLen); 231 copyStreams(oos, dis, mapLen + pathLen * 2); 232 } 233 } 234 } 235 } catch (Exception e) { 236 ErrorManager.getDefault().annotate(e, "Copy: " + store.getAbsolutePath() + " to: " + storeNew.getAbsolutePath()); ErrorManager.getDefault().notify(e); 238 return true; 239 } finally { 240 if (oos != null) try { oos.close(); } catch (IOException e) {} 241 if (dis != null) try { dis.close(); } catch (IOException e) {} 242 } 243 storeSerial++; 244 try { 245 FileUtils.renameFile(storeNew, store); 246 } catch (IOException ex) { 247 ErrorManager.getDefault().notify(ex); 248 } 249 return true; 250 } 251 252 private void skip(InputStream is, long len) throws IOException { 253 while (len > 0) { 254 long n = is.skip(len); 255 if (n < 0) throw new EOFException("Missing " + len + " bytes."); len -= n; 257 } 258 } 259 260 private String readChars(DataInputStream dis, int len) throws IOException { 261 StringBuffer sb = new StringBuffer (len); 262 while (len-- > 0) { 263 sb.append(dis.readChar()); 264 } 265 return sb.toString(); 266 } 267 268 private Map<File, FileInformation> readValue(DataInputStream dis, String dirPath) throws IOException { 269 Map<File, FileInformation> map = new HashMap<File, FileInformation>(); 270 int len = dis.readInt(); 271 while (len-- > 0) { 272 int nameLen = dis.readInt(); 273 String name = readChars(dis, nameLen); 274 File file = new File(dirPath, name); 275 int status = dis.readInt(); 276 FileInformation info = new FileInformation(status & 65535, status > 65535); 277 map.put(file, info); 278 } 279 return map; 280 } 281 282 private void writeEntry(DataOutputStream dos, String dirPath, Object value) throws IOException { 283 284 Map map = (Map) value; 285 Set set = map.keySet(); 286 ByteArrayOutputStream baos = new ByteArrayOutputStream(set.size() * 50); 287 DataOutputStream temp = new DataOutputStream(baos); 288 289 temp.writeInt(set.size()); 290 for (Iterator i = set.iterator(); i.hasNext();) { 291 File file = (File) i.next(); 292 FileInformation info = (FileInformation) map.get(file); 293 temp.writeInt(file.getName().length()); 294 temp.writeChars(file.getName()); 295 temp.writeInt(info.getStatus() + (info.isDirectory() ? 65536 : 0)); 296 } 297 temp.close(); 298 byte [] valueBytes = baos.toByteArray(); 299 300 dos.writeInt(dirPath.length()); 301 dos.writeInt(valueBytes.length); 302 dos.writeChars(dirPath); 303 dos.write(valueBytes); 304 } 305 306 private boolean isValuable(Object value) { 307 Map map = (Map) value; 308 for (Iterator i = map.values().iterator(); i.hasNext();) { 309 FileInformation info = (FileInformation) i.next(); 310 if ((info.getStatus() & STATUS_VALUABLE) != 0) return true; 311 } 312 return false; 313 } 314 315 private File getStore(File dir) { 316 String dirPath = dir.getAbsolutePath(); 317 int dirHash = dirPath.hashCode(); 318 return new File(cacheStore, Integer.toString(dirHash % 173 + 172) + ".bin"); } 320 321 private void initCacheStore() { 322 String userDir = System.getProperty("netbeans.user"); if (userDir != null) { 324 cacheStore = new File(new File(new File (userDir, "var"), "cache"), CACHE_DIRECTORY); } else { 326 File cachedir = FileUtil.toFile(Repository.getDefault().getDefaultFileSystem().getRoot()); 327 cacheStore = new File(cachedir, CACHE_DIRECTORY); } 329 cacheStore.mkdirs(); 330 } 331 332 private static void copyStreams(OutputStream out, InputStream in, int len) throws IOException { 333 byte [] buffer = new byte[4096]; 334 for (;;) { 335 int n = (len <= 4096) ? len : 4096; 336 n = in.read(buffer, 0, n); 337 if (n < 0) throw new EOFException("Missing " + len + " bytes."); out.write(buffer, 0, n); 339 if ((len -= n) == 0) break; 340 } 341 out.flush(); 342 } 343 } 344 | Popular Tags |