Changeset 12451
- Timestamp:
- 02/12/10 11:08:20 (13 years ago)
- Location:
- trunk/abcl/src/org/armedbear/lisp
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/abcl/src/org/armedbear/lisp/Autoload.java
r12441 r12451 607 607 autoload(PACKAGE_SYS, "default-time-zone", "Time"); 608 608 autoload(PACKAGE_SYS, "disassemble-class-bytes", "disassemble_class_bytes", true); 609 autoload(PACKAGE_SYS, "disable-zip-cache", "ZipCache", true); 609 610 autoload(PACKAGE_SYS, "double-float-high-bits", "FloatFunctions", true); 610 611 autoload(PACKAGE_SYS, "double-float-low-bits", "FloatFunctions", true); -
trunk/abcl/src/org/armedbear/lisp/ZipCache.java
r12448 r12451 37 37 38 38 import java.io.File; 39 import java.io.InputStream; 39 40 import java.io.IOException; 40 41 import java.net.JarURLConnection; … … 42 43 import java.net.URL; 43 44 import java.net.URLConnection; 45 import java.util.Enumeration; 44 46 import java.util.HashMap; 45 47 import java.util.zip.ZipException; 46 48 import java.util.zip.ZipFile; 49 import java.util.zip.ZipEntry; 47 50 48 51 /** 49 52 * A cache for all zip/jar file accesses by URL that uses the last 50 53 * modified time of the cached resource. 54 * 55 * This implementation is NOT thread safe, although usage without 56 * multiple threads recompiling code that is then re-loaded should be 57 * fine. 58 * 59 * If you run into problems with caching, use 60 * (SYS::DISABLE-ZIP-CACHE). Once disabled, the caching cannot be 61 * re-enabled. 62 * 51 63 */ 52 64 public class ZipCache { 53 static class Entry { 54 long lastModified; 55 ZipFile file; 56 } 57 58 static HashMap<URL, Entry> zipCache = new HashMap<URL, Entry>(); 59 60 public static ZipFile get(LispObject arg) { 61 return get(Pathname.makeURL(arg)); 62 } 63 64 public static ZipFile get(URL url) { 65 Entry entry = zipCache.get(url); 66 if (entry != null) { 67 if (url.getProtocol().equals("file")) { 68 File f = new File(url.getPath()); 65 66 // To make this thread safe, we should return a proxy for ZipFile 67 // that keeps track of the number of outstanding references handed 68 // out, not allowing ZipFile.close() to succeed until that count 69 // has been reduced to 1 or the finalizer is executing. 70 // Unfortunately the relatively simple strategy of extended 71 // ZipFile via a CachedZipFile does not work because there is not 72 // a null arg constructor for ZipFile. 73 static class Entry { 74 long lastModified; 75 ZipFile file; 76 } 77 78 static boolean cacheEnabled = true; 79 80 private final static Primitive DISABLE_ZIP_CACHE = new disable_zip_cache(); 81 final static class disable_zip_cache extends Primitive { 82 disable_zip_cache() { 83 super("disable-zip-cache", PACKAGE_SYS, true, "", 84 "Disable all caching of ABCL FASLs and ZIPs."); 85 } 86 @Override 87 public LispObject execute() { 88 ZipCache.disable(); 89 return T; 90 } 91 } 92 93 static public synchronized void disable() { 94 cacheEnabled = false; 95 zipCache.clear(); 96 } 97 98 static HashMap<URL, Entry> zipCache = new HashMap<URL, Entry>(); 99 100 synchronized public static ZipFile get(LispObject arg) { 101 return get(Pathname.makeURL(arg)); 102 } 103 104 synchronized public static ZipFile get(final URL url) { 105 if (!cacheEnabled) { 106 if (url.getProtocol().equals("file")) { 107 File f = new File(url.getPath()); 108 try { 109 return new ZipFile(f); 110 } catch (ZipException e) { 111 Debug.trace(e); // XXX 112 return null; 113 } catch (IOException e) { 114 Debug.trace(e); // XXX 115 return null; 116 } 117 } else { 118 Entry e = fetchURL(url, false); 119 return e.file; 120 } 121 } 122 123 Entry entry = zipCache.get(url); 124 125 // Check that the cache entry still accesses a valid ZipFile 126 if (entry != null) { 127 // Simplest way to call private ZipFile.ensureOpen() 128 try { 129 int size = entry.file.size(); 130 } catch (IllegalStateException e) { 131 zipCache.remove(url); 132 entry = null; 133 } 134 } 135 136 if (entry != null) { 137 if (url.getProtocol().equals("file")) { 138 File f = new File(url.getPath()); 69 139 long current = f.lastModified(); 70 140 if (current > entry.lastModified) { 71 141 try { 72 entry.file.close(); 73 entry.file = new ZipFile(f); 74 entry.lastModified = current; 142 entry.file = new ZipFile(f); 143 entry.lastModified = current; 75 144 } catch (IOException e) { 76 145 Debug.trace(e.toString()); // XXX … … 78 147 } 79 148 } else { 80 // Unfortunately, the Apple JDK under OS X doesn't do81 // HTTP HEAD requests, instead refetching the entire82 // resource, so the following code is a waste. I assume83 // this is the case in all Sun-dervied JVMs. We'll have84 // to implement a custom HTTP lastModified checker.85 86 // URLConnection connection;87 // try {88 // connection = url.openConnection();89 // } catch (IOException ex) {90 // Debug.trace("Failed to open "91 // + "'" + url + "'");92 // return null;93 // }94 // long current = connection.getLastModified();95 // if (current > entry.lastModified) {96 // try {97 // entry.file.close();98 // } catch (IOException ex) {}99 // entry = fetchURL(url, false);100 // }149 // Unfortunately, the Apple JDK under OS X doesn't do 150 // HTTP HEAD requests, instead refetching the entire 151 // resource, so the following code is a waste. I assume 152 // this is the case in all Sun-dervied JVMs. We'll have 153 // to implement a custom HTTP lastModified checker. 154 155 // URLConnection connection; 156 // try { 157 // connection = url.openConnection(); 158 // } catch (IOException ex) { 159 // Debug.trace("Failed to open " 160 // + "'" + url + "'"); 161 // return null; 162 // } 163 // long current = connection.getLastModified(); 164 // if (current > entry.lastModified) { 165 // try { 166 // entry.file.close(); 167 // } catch (IOException ex) {} 168 // entry = fetchURL(url, false); 169 // } 101 170 } 102 171 } else { 103 if (url.getProtocol().equals("file")) {172 if (url.getProtocol().equals("file")) { 104 173 entry = new Entry(); 105 174 File f = new File(url.getPath()); … … 120 189 } 121 190 return entry.file; 122 }191 } 123 192 124 static private Entry fetchURL(URL url, boolean cached) { 125 Entry result = new Entry(); 126 URL jarURL = null; 127 try { 128 jarURL = new URL("jar:" + url + "!/"); 129 } catch (MalformedURLException e) { 130 Debug.trace(e); 131 Debug.assertTrue(false); // XXX 132 } 133 URLConnection connection; 134 try { 135 connection = jarURL.openConnection(); 136 } catch (IOException ex) { 137 Debug.trace("Failed to open " 138 + "'" + jarURL + "'"); 139 return null; 140 } 141 if (!(connection instanceof JarURLConnection)) { 142 // XXX 143 Debug.trace("Could not get a URLConnection from " + jarURL); 144 return null; 145 } 146 JarURLConnection jarURLConnection = (JarURLConnection) connection; 147 jarURLConnection.setUseCaches(cached); 148 try { 149 result.file = jarURLConnection.getJarFile(); 150 } catch (IOException e) { 151 Debug.trace(e); 152 Debug.assertTrue(false); // XXX 153 } 154 result.lastModified = jarURLConnection.getLastModified(); 155 return result; 156 } 157 158 159 160 // ## remove-zip-cache-entry pathname => boolean 161 private static final Primitive REMOVE_ZIP_CACHE_ENTRY = new remove_zip_cache_entry(); 162 private static class remove_zip_cache_entry extends Primitive { 163 remove_zip_cache_entry() { 164 super("remove-zip-cache-entry", PACKAGE_SYS, true, "pathname"); 165 } 166 @Override 167 public LispObject execute(LispObject arg) { 168 Pathname p = coerceToPathname(arg); 169 boolean result = ZipCache.remove(p); 170 return result ? T : NIL; 171 } 172 } 193 static private Entry fetchURL(URL url, boolean cached) { 194 Entry result = new Entry(); 195 URL jarURL = null; 196 try { 197 jarURL = new URL("jar:" + url + "!/"); 198 } catch (MalformedURLException e) { 199 Debug.trace(e); 200 Debug.assertTrue(false); // XXX 201 } 202 URLConnection connection; 203 try { 204 connection = jarURL.openConnection(); 205 } catch (IOException ex) { 206 Debug.trace("Failed to open " 207 + "'" + jarURL + "'"); 208 return null; 209 } 210 if (!(connection instanceof JarURLConnection)) { 211 // XXX 212 Debug.trace("Could not get a URLConnection from " + jarURL); 213 return null; 214 } 215 JarURLConnection jarURLConnection = (JarURLConnection) connection; 216 jarURLConnection.setUseCaches(cached); 217 try { 218 result.file = jarURLConnection.getJarFile(); 219 } catch (IOException e) { 220 Debug.trace(e); 221 Debug.assertTrue(false); // XXX 222 } 223 result.lastModified = jarURLConnection.getLastModified(); 224 return result; 225 } 226 227 // ## remove-zip-cache-entry pathname => boolean 228 private static final Primitive REMOVE_ZIP_CACHE_ENTRY = new remove_zip_cache_entry(); 229 private static class remove_zip_cache_entry extends Primitive { 230 remove_zip_cache_entry() { 231 super("remove-zip-cache-entry", PACKAGE_SYS, true, "pathname"); 232 } 233 @Override 234 public LispObject execute(LispObject arg) { 235 Pathname p = coerceToPathname(arg); 236 boolean result = ZipCache.remove(p); 237 return result ? T : NIL; 238 } 239 } 173 240 174 public static boolean remove(URL url) { 175 Entry entry = zipCache.get(url); 176 if (entry != null) { 177 try { 178 entry.file.close(); 179 } catch (IOException e) {} 180 zipCache.remove(entry); 181 return true; 182 } 183 return false; 184 } 185 186 public static boolean remove(Pathname p) { 187 URL url = Pathname.makeURL(p); 188 if (url == null) { 189 return false; 190 } 191 return ZipCache.remove(url); 192 } 193 194 public static boolean remove(File f) { 195 Pathname p = Pathname.makePathname(f); 196 return ZipCache.remove(p); 197 } 198 241 synchronized public static boolean remove(URL url) { 242 Entry entry = zipCache.get(url); 243 if (entry != null) { 244 try { 245 entry.file.close(); 246 } catch (IOException e) {} 247 zipCache.remove(entry); 248 return true; 249 } 250 return false; 251 } 252 253 synchronized public static boolean remove(Pathname p) { 254 URL url = Pathname.makeURL(p); 255 if (url == null) { 256 return false; 257 } 258 return ZipCache.remove(url); 259 } 260 261 synchronized public static boolean remove(File f) { 262 Pathname p = Pathname.makePathname(f); 263 return ZipCache.remove(p); 264 } 199 265 }
Note: See TracChangeset
for help on using the changeset viewer.