📄 resourcestoremanager.java
字号:
*/ private int loadedStore = 0; /** * Is this store shutdown ? */ protected boolean closed = false ; /** * Our store directory. */ protected File storedir = null; /** * Our index file. */ protected File index = null; /** * server name; */ protected String server_name = null; /** * Our root repository. */ protected File root_repository = null; /** * The store entries least recetenly used list. */ protected LRUList lru = null; // FIXME doc protected ResourceStoreState state = null; /** * Our sweeper thread: */ protected StoreManagerSweeper sweeper = null ; protected ResourceEventQueue eventQueue = null; public ResourceEventQueue getEventQueue() { if (eventQueue == null) eventQueue = new ResourceEventQueue(); return eventQueue; } protected final int getMaxLoadedStore() { return maxLoadedStore ; } protected final int getStoreSizeLimit() { return storeSizeLimit; } protected void incrLoadedStore() { loadedStore++; checkMaxLoadedStore(); } protected void decrLoadedStore() { loadedStore--; } /** * Check that this resource store manager isn't closed. * @exception RuntimeException If the store manager was closed. */ protected final synchronized void checkClosed() { if ( closed ) throw new RuntimeException("Invalid store manager access.") ; } /** * Pick the least recently used entry, and remove all links to it. * After this method as run, the least recently used entry for some store * will be returned. The store manager will have discarded all its link to * it, and the entry shutdown will have to be performed by the caller. * @return An StoreEntry instance, to be cleaned up. */ protected synchronized NewStoreEntry pickLRUEntry() { return (NewStoreEntry) lru.removeTail(); } /** * Collect enough entries to go back into fixed limits. */ public void collect() { if (debugMemory) System.out.println("[MEMORY] start sweeper <- "+ loadedStore+" stores loaded."); NewStoreEntry watchdog = null; NewStoreEntry entry = null; while ( loadedStore > getMaxLoadedStore() ) { entry = pickLRUEntry(); if (( entry != null ) && (entry != watchdog)) { synchronized(entry) { if (! entry.unloadStore()) { lru.toHead(entry); if (watchdog == null) watchdog = entry; } } } else { break; } } if (debugMemory) System.out.println("[MEMORY] sweeper done -> "+ loadedStore+" stores still loaded."); } /** * Create a resource store repository name. * This method will return a new resource store repository key. When * used in conjunction with the <code>loadResourceStore</code> method * that takes a key as a parameter, this allows to caller to abstract * itself from the physical location of the repository. * @return A fresh resource store key, guaranteed to be uniq. */ public synchronized String createResourceStoreRepository() { int key = state.getNextKey(); return (key%SUBDIRS)+"/st-" + key; } public int getCurrentStoreIdentifier() { return state.getCurrentKey(); } protected boolean checkSubDirs() { for (int i = 0 ; i < SUBDIRS ; i++) { File subd = new File(storedir, Integer.toString(i)); if ((! subd.exists()) && ! subd.mkdirs()) return false; } return true; } /** * Get the index file. * @return A File instance. */ protected File getIndexFile() { if (index == null) index = new File(storedir,server_name+"-index.xml"); return index; } /** * Get the index file. * @return A File instance. */ protected File getOldIndexFile() { if (index == null) index = new File(storedir,server_name+"-index"); return index; } /** * Get the root repository. * @return A File instance. */ protected File getRootRepository() { if (root_repository == null) root_repository = new File(storedir,ROOT_REP); return root_repository; } /** * Get The root key. * @return A String instance */ protected Integer getRootKey() { return new Integer((new String("root")).hashCode()); } /** * Emit the given string as a warning, to whoever it is appropriate. * @param msg The warning message. */ protected void warning(String msg) { System.out.println("********* WARNING *********"); System.out.println("[" + getClass().getName()+"]:\n" + msg) ; System.out.println("***************************"); } protected synchronized void saveNewEntriesIndex() { File indexFile = getIndexFile(); String dir = indexFile.getParent(); String name = indexFile.getName(); File tmp = new File(dir, name+".tmp"); File bak = new File(dir, name+".bak"); File tild = new File(dir, name+".bak~"); Enumeration elements = entries.elements(); Vector v = new Vector(10); while (elements.hasMoreElements()) { NewStoreEntry entry = (NewStoreEntry) elements.nextElement(); if (! entry.isTransient()) v.addElement(entry); } NewStoreEntry se[] = new NewStoreEntry[v.size()]; v.copyInto(se); try { FileOutputStream fos = new FileOutputStream(tmp); Writer writer = new BufferedWriter( new OutputStreamWriter(fos,"UTF-8")); serializer.writeResources(se, writer); } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException("Unable to save entries index"); } // 1st move: delete the ~ file if any: if ( tild.exists() ) tild.delete() ; // 2nd move rename bak to ~ (bak no longer exists) if ( bak.exists() ) { bak.renameTo(tild); bak.delete(); } // 3nd move: rename the current index to bak if ( indexFile.exists() ) { if ( !indexFile.renameTo(bak) ) { warning("unable to rename "+indexFile+" to "+bak); tild.renameTo(bak); } indexFile.delete(); } // 4th move: rename the tmp file to index if ( !tmp.renameTo(indexFile) ) { bak.renameTo(indexFile) ; tild.renameTo(bak); warning("unable to rename "+tmp+" to "+indexFile); } // cleanup (erase the ~ file) tild.delete() ; } protected synchronized void loadNewEntriesIndex() { File indexFile = getIndexFile(); if (! indexFile.exists()) { File bak = new File(indexFile.getParent(), indexFile.getName()+".bak"); if (bak.exists()) { warning(indexFile+" not found! using bak file :"+bak); if ( !bak.renameTo(indexFile) ) { warning("unable to rename "+bak+" to "+indexFile+ "\n Try by yourself or all your resources will be lost!"); System.exit(-1); } } else { entries = new Hashtable(256); return; } } entries = new Hashtable(256); try { Reader reader = new BufferedReader(new FileReader(indexFile)); AttributeHolder holders[] = serializer.readAttributeHolders(reader); for (int i = 0 ; i < holders.length ; i++) { NewStoreEntry entry = (NewStoreEntry) holders[i]; entries.put(entry.getKey(), entry); lru.toHead((LRUAble) entry); entry.initialize(this); } } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException("Unable to load entries index"); } } /** * update the old index file. Load it and save it with the serializer. * @param the index file (serialized hashtable of StoreEntry) */ public static synchronized void updateEntriesIndex(File oldIndexFile, File newIndexFile, Serializer serializer) throws IOException { Hashtable entries = new Hashtable(); if (! oldIndexFile.exists()) { File bak = new File(oldIndexFile.getParent(), oldIndexFile.getName()+".bak"); if (bak.exists()) { System.out.println(oldIndexFile.getAbsolutePath()+ " not found! using bak file :"+bak); if ( !bak.renameTo(oldIndexFile) ) { System.out.println("unable to rename "+bak+" to "+ oldIndexFile+ "\n Try by yourself or all your resources will be lost!"); System.exit(-1); } } else { return; } } ObjectInputStream oi = null; try { oi = new ObjectInputStream(new BufferedInputStream (new FileInputStream (oldIndexFile))); entries = (Hashtable) oi.readObject(); } catch (ClassNotFoundException ex) { ex.printStackTrace(); throw new RuntimeException("Unable to load entries index"); } catch (IOException ex) { ex.printStackTrace(); throw new RuntimeException("Unable to load entries index"); } finally { if ( oi != null ) { try { oi.close() ; } catch (Exception ex) {} } } Enumeration e = entries.elements(); int len = 0; while (e.hasMoreElements()) { StoreEntry entry = (StoreEntry)e.nextElement(); if (entry.isTransient()) entries.remove(entry.key); else { len++; String rep = entry.repository; if (rep != null) { if (rep.equals("root.idx")) { entry.repository = "root.xml"; } else { // st-xxx int number = Integer.parseInt(rep.substring(3)); entry.repository = (number%SUBDIRS)+"/"+rep; } } } } //StoreEntry => NewStoreEntry e = entries.elements(); NewStoreEntry nentries[] = new NewStoreEntry[len]; int i = 0; while (e.hasMoreElements()) { StoreEntry entry = (StoreEntry)e.nextElement(); NewStoreEntry nentry = new NewStoreEntry(null, entry.repository, entry.key); nentries[i++] = nentry; } FileOutputStream fos = new FileOutputStream(newIndexFile); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); Writer writer = new BufferedWriter(osw); serializer.writeResources(nentries, writer); } /** * Shutdown this resource store manager. * Go through all entries, and shut them down. */ public synchronized void shutdown() { saveNewEntriesIndex(); // Kill the sweeper thread: sweeper.shutdown() ; // Clenup all pending resource stores: Enumeration enum = entries.elements() ; while ( enum.hasMoreElements() ) { NewStoreEntry entry = (NewStoreEntry) enum.nextElement() ; entry.shutdownStore() ; entries.remove(entry.getKey()) ; } closed = true ; // Now save our state: File rmstate = new File(storedir, STATE_F); try { FileOutputStream fos = new FileOutputStream(rmstate); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); Writer writer = new BufferedWriter ( osw ); AttributeHolder statearray[] = { state }; serializer.writeResources(statearray, writer); } catch (Exception ex) { // FIXME !! System.out.println("ResourceStoreManager: unable to save state !"); ex.printStackTrace(); } } /** * Checkpoint all modified resource stores, by saving them to disk. */ public void checkpoint() { try { saveNewEntriesIndex(); } catch (Exception ex) { System.out.println("*** Error during checkpoint"); } // Checkpoint all loaded resource stores: Enumeration e = entries.elements(); while ( e.hasMoreElements() ) { NewStoreEntry entry = (NewStoreEntry) e.nextElement(); try { entry.saveStore(); } catch (Exception ex) { if (entry == null) { System.out.println("*** Error, saving null entry!"); } else { System.out.println("*** Error while saving store " + entry.getKey()); } } } // Then save our state: File rmstate = new File(storedir, STATE_F); try { FileOutputStream fos = new FileOutputStream(rmstate); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); Writer writer = new BufferedWriter ( osw ); AttributeHolder statearray[] = { state }; serializer.writeResources(statearray, writer); } catch (Exception ex) { // FIXME !! System.out.println("ResourceStoreManager: unable to save state !"); ex.printStackTrace(); } } /** * Mark the given store as having been used recently. * @param token The token the resource store manager provided you when * it initialized the store. */ public void markUsed(Object token) { NewStoreEntry entry = (NewStoreEntry) token; if ( entry != null ) lru.toHead(entry); } protected boolean used(String rep) { Enumeration e = entries.elements(); NewStoreEntry entry = null; while (e.hasMoreElements()) { entry = (NewStoreEntry)e.nextElement(); System.out.println(storedir+":"+entry.getRepository()); try { if (entry.getRepository().getName().equals(rep)) return true; } catch (Exception ex) { //continue } } return false; } public void salvage() { String stores[] = storedir.list(); if ( stores != null ) { for (int i = 0 ; i < stores.length; i++) { if ((stores[i].length() <= 3) || ! stores[i].startsWith("st-")) continue; if ( stores[i].endsWith(".bak") ) continue; //Is there a storeEntry using this repository? if (! used(stores[i])) { // For testing now System.err.println("*** "+stores[i]+" not used! deleted"); File notUsed = new File(storedir, stores[i]); notUsed.delete(); } } } } public void displayIndex() { Enumeration e = entries.elements(); NewStoreEntry entry = null; System.out.println("Index : "); while (e.hasMoreElements()) { entry = (NewStoreEntry)e.nextElement(); System.out.println(entry.getKey()+" : "+entry.getRepository()); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -