ncache.java
来自「一款Java实现的HTTP代理服务器」· Java 代码 · 共 620 行 · 第 1/2 页
JAVA
620 行
String newName = getEntryName (ent.getId (), true); File nFile = new File (newName); synchronized (dirLock) { if (f.exists ()) { if (f.isFile ()) { logger.logWarn ("Wanted cachedir is a file!"); } // good situation... } else { f.mkdir (); } boolean bool = cfile.renameTo (nFile); } cfile = new File (newName); ent.setSize (cfile.length ()); ent.setCacheTime (System.currentTimeMillis ()); NCacheEntry<K, V> nent = (NCacheEntry<K, V>)ent; storeHook (nent); K realKey = ent.getKey (); FiledKey<K> fk = new FiledKey<K> (); fk.storeKey (this, ent, realKey); w.lock (); try { nent.setKey (fk); remove (realKey); htab.put (fk, ent); currentSize += ent.getSize (); vec.add (ent); } finally { w.unlock (); } changed = true; } private void storeHook (NCacheEntry<K, V> nent) { V hook = nent.getDataHook (this); if (hook != null) { FiledHook<V> fh = new FiledHook<V> (); fh.storeHook (this, nent, hook); nent.setFiledDataHook (fh); } } /** Signal that a cache entry have changed. */ public void entryChanged (CacheEntry<K, V> ent, K newKey, V newHook) { NCacheEntry<K, V> nent = (NCacheEntry<K, V>)ent; FiledHook<V> fh = new FiledHook<V> (); fh.storeHook (this, nent, newHook); nent.setFiledDataHook (fh); FiledKey<K> fk = new FiledKey<K> (); fk.storeKey (this, nent, newKey); changed = true; } private void removeHook (String base, String extension) { String hookName = base + extension; // remove possible hook before file... File hfile = new File (hookName); if (hfile.exists ()) hfile.delete (); } /** Remove the Entry with key k from the cache. * @param k the key for the CacheEntry. */ public void remove (K k) { CacheEntry<K, V> rent; w.lock (); try { if (k == null) { // Odd, but seems to happen. Probably removed // by someone else before enumeration gets to it. return; } FiledKey fk = new MemoryKey<K> (k); rent = htab.get (fk); if (rent != null) { // remove entries while it is still in htab. vec.remove (rent); currentSize -= rent.getSize (); htab.remove (fk); } } finally { w.unlock (); } if (rent != null) { // this removes the key => htab.remove can not work.. String entryName = getEntryName (rent); removeHook (entryName, ".hook"); removeHook (entryName, ".key"); NCacheEntry<K, V> nent = (NCacheEntry<K, V>)rent; nent.setKey (null); rent.setDataHook (null); File cfile = new File (entryName); if (cfile.exists ()) { File p = cfile.getParentFile (); cfile.delete (); // Until NT does rename in a nice manner check for tempdir. synchronized (dirLock) { if (p.exists () && !p.equals (tempdir)) { String ls[] = p.list (); if (ls != null && ls.length == 0) p.delete(); } } } } } /** Clear the Cache from files. */ public void clear () { ArrayList<FiledKey<K>> ls; w.lock (); try { ls = new ArrayList<FiledKey<K>> (htab.keySet ()); for (FiledKey<K> k : ls) remove (k.getData ()); vec.clear (); // just to be safe. currentSize = 0; changed = true; } finally { w.unlock (); } } /** Get the CacheEntries in the cache. * Note! some entries may be invalid if you have a corruct cache. * @return an Enumeration of the CacheEntries. */ public Collection<CacheEntry<K, V>> getEntries () { return htab.values (); } /** Read the info from an old cache. */ @SuppressWarnings( "unchecked" ) private void readCacheIndex () { fileNo = 0; currentSize = 0; htab = new HashMap<FiledKey<K>, CacheEntry<K, V>> (); vec = new ArrayList<CacheEntry<K, V>> (); try { String name = dir + File.separator + CACHEINDEX; FileInputStream fis = new FileInputStream (name); ObjectInputStream is = new ObjectInputStream (new GZIPInputStream (fis)); fileNo = is.readLong (); currentSize = is.readLong (); int size = is.readInt (); Map<FiledKey<K>, CacheEntry<K, V>> hh = new HashMap<FiledKey<K>, CacheEntry<K, V>> ((int)(size * 1.2)); for (int i = 0; i < size; i++) { FiledKey<K> fk = (FiledKey<K>)is.readObject (); fk.setCache (this); NCacheEntry<K, V> entry = (NCacheEntry<K, V>)is.readObject (); entry.setKey (fk); hh.put (fk, entry); } htab = hh; vec = (List<CacheEntry<K, V>>)is.readObject (); is.close (); } catch (IOException e) { logger.logWarn ("Couldnt read " + dir + File.separator + CACHEINDEX + ", This is bad( but not serius).\n" + "Treating as empty. " + e); } catch (ClassNotFoundException e) { logger.logError("Couldn't find classes: " + e); } } /** Make sure that the cache is written to the disk. */ public void flush () { writeCacheIndex (); } /** Store the cache to disk so we can reuse it later. */ private void writeCacheIndex () { try { String name = dir + File.separator + CACHEINDEX; FileOutputStream fos = new FileOutputStream (name); ObjectOutputStream os = new ObjectOutputStream (new GZIPOutputStream (fos)); r.lock (); try { os.writeLong (fileNo); os.writeLong (currentSize); os.writeInt (htab.size ()); for (Map.Entry<FiledKey<K>, CacheEntry<K, V>> me : htab.entrySet ()) { os.writeObject (me.getKey ()); os.writeObject (me.getValue ()); } os.writeObject (vec); } finally { r.unlock (); } os.close (); } catch (IOException e) { logger.logWarn ("Couldnt write " + dir + File.separator + CACHEINDEX + ", This is serious!\n" + e); } } /** Loop in a cleaning loop. */ public void run () { Thread.currentThread ().setPriority (Thread. MIN_PRIORITY); while (running) { try { Thread.sleep (cleanLoopTime); } catch (InterruptedException e) { //System.err.println ("Cache interrupted"); } if (!running) continue; // actually for a busy cache this will lag... // but I dont care for now... long milis = System.currentTimeMillis (); Collection<CacheEntry<K, V>> entries; r.lock (); try { entries = new ArrayList<CacheEntry<K, V>> (htab.values ()); } finally { r.unlock (); } for (CacheEntry<K, V> ce : entries) { long exp = ce.getExpires (); if (exp < milis) remove (ce.getKey ()); } // IF SIZE IS TO BIG REMOVE A RANDOM AMOUNT OF OBJECTS. // What we have to be careful about: we must not remove the same // elements two times in a row, this method remove the "oldest" in // a sense. if (getCurrentSize () > getMaxSize ()) changed = true; while (getCurrentSize () > getMaxSize ()) { w.lock (); try { remove (vec.get (0).getKey ()); } finally { w.unlock (); } } if (changed) { writeCacheIndex (); changed = false; } } } public void stop () { running = false; if (cleaner != null) { try { cleaner.interrupt (); cleaner.join (); } catch (InterruptedException e) { // ignore } } } /** Configure the cache system from the given config. * @param config the properties describing the cache settings. */ public void setup (Logger logger, SProperties config) { if (config == null) return; String cachedir = config.getProperty ("directory", "/tmp/rabbit/cache/"); setCacheDir (cachedir); String cmsize = config.getProperty ("maxsize", "10"); try { setMaxSize (Long.parseLong (cmsize) * 1024 * 1024); // in MB } catch (NumberFormatException e) { logger.logWarn ("Bad number for cache maxsize: '" + cmsize + "'"); } String ctime = config.getProperty ("cachetime", "24"); try { setCacheTime (Long.parseLong (ctime) * 1000 * 60 * 60); // in hours. } catch (NumberFormatException e) { logger.logWarn ("Bad number for cache cachetime: '" + ctime + "'"); } String ct = config.getProperty ("cleanloop", "60"); try { setCleanLoopTime (Integer.parseInt (ct) * 1000); // in seconds. } catch (NumberFormatException e) { logger.logWarn ("Bad number for cache cleanloop: '" + ct + "'"); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?