📄 magicstore.java
字号:
// You can redistribute this software and/or modify it under the terms of// the Ozone Core License version 1 published by ozone-db.org.//// The original code and portions created by SMB are// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.//// $Id: MagicStore.java,v 1.8 2004/01/22 07:48:59 leomekenkamp Exp $package org.ozoneDB.core.storage.magicStore;import java.io.*;import java.util.Iterator;import java.util.Set;import org.ozoneDB.DxLib.*;import org.ozoneDB.*;import org.ozoneDB.io.stream.ResolvingObjectInputStream;import org.ozoneDB.core.*;import org.ozoneDB.core.storage.ClusterID;import org.ozoneDB.core.storage.Cluster;import org.ozoneDB.core.storage.StorageObjectContainer;import org.ozoneDB.util.LogWriter;/** * @author <a href="http://www.softwarebuero.de/">SMB</a> * @author <a href="http://www.medium.net/">Medium.net</a> * @author Leo Mekenkamp * @author Per Nyfelt * @version $Revision: 1.8 $Date: 2004/01/22 07:48:59 $ */public final class MagicStore extends ServerComponent implements StoreManager { protected final static String ID_TABLE_NAME = "idTable.wizard"; protected final static String NAME_TABLE_NAME = "nameTable.wizard"; protected final static String COMMIT_FLAG_NAME = "commitflag.wizard"; /** * Maps ObjectIDs to ClusterIDs */ protected DxMap idTable; /** * Maps names to ObjectIDs */ protected DxMap nameTable; protected ClusterStore clusterStore; /** The garbage collector. It should be notified in the event <UL> <LI>that a formerly unnamed object receives a name.</LI> <LI>that an object is freshly created</LI> </LI> */ protected GarbageCollector garbageCollector; public MagicStore(Env env) { super(env); } public synchronized void init(Env _env) { env = _env; int idTableBufferSize = env.config.intProperty(Setup.WS_TABLE_BUFF_SIZE, -1); int idTableCacheSize = env.config.intProperty(Setup.WS_TABLE_CACHE_SIZE, -1); int[] idTableSubtableSize = env.config.intArrayProperty(Setup.WS_TABLE_SUBTABLE_SIZE, new int[] {-1}); idTable = new IDTable(env.getDatabaseDir() + "ostab" + File.separator + "tab", idTableBufferSize, idTableCacheSize, idTableSubtableSize); // idTable = new DxHashMap (10000); nameTable = new DxHashMap(100); clusterStore = new ClusterStore(env); clusterStore.setMagicStore(this); this.garbageCollector = env.getGarbageCollector(); } public synchronized void startup() throws Exception { env.logWriter.newEntry(this, "startup...", LogWriter.INFO); env.logWriter.newEntry(this, "CAUTION: MagicStore is still in early development phase, use with caution!", LogWriter.INFO); clusterStore.startup(); env.logWriter.newEntry(this, "checking for pending shadow clusters...", LogWriter.INFO); boolean isCleanShutdown = isCleanShutdown() && clusterStore.isCleanShutdown(); boolean isSuccessfullyStarted = false; if (isCleanShutdown) { ObjectInputStream nameTableIn = null; ObjectInputStream idTableIn = null; try { // restore nameTable nameTableIn = new ResolvingObjectInputStream(new FileInputStream(env.getDatabaseDir() + NAME_TABLE_NAME)); int count = nameTableIn.readInt(); for (int i = 0; i < count; i++) { nameTable.addForKey(nameTableIn.readObject(), nameTableIn.readObject()); } nameTableIn.close(); // restore idTable if (!(idTable instanceof DxDiskHashMap)) { idTableIn = new ResolvingObjectInputStream(new FileInputStream(env.getDatabaseDir() + ID_TABLE_NAME)); count = idTableIn.readInt(); for (int i = 0; i < count; i++) { idTable.addForKey(idTableIn.readObject(), idTableIn.readObject()); } idTableIn.close(); } else { ((DxDiskHashMap) idTable).re_use(); ((DxDiskHashMap) idTable).setReusable(true); } isSuccessfullyStarted = true; } catch (FileNotFoundException fe) { env.logWriter.newEntry(this, " " + fe.toString(), LogWriter.INFO); } catch (Exception e) { env.logWriter.newEntry(this, " error while starting up... ", LogWriter.INFO); env.logWriter.newEntry(this, " exception: ", e, LogWriter.DEBUG); } finally { if (nameTableIn != null) { nameTableIn.close(); } if (idTableIn != null) { idTableIn.close(); } } } if (!isCleanShutdown || !isSuccessfullyStarted) { env.logWriter.newEntry(this, " recovering...", LogWriter.INFO); recover(); } env.logWriter.newEntry(this, " " + idTable.count() + " IDs, " + nameTable.count() + " name(s))", LogWriter.INFO); } public synchronized void shutdown() throws Exception { env.logWriter.newEntry(this, "shutdown...", LogWriter.INFO); clusterStore.shutdown(); commitNameTable(); commitIDTable(); if (idTable instanceof DxDiskHashMap) { ((DxDiskHashMap) idTable).printStatistics(); ((DxDiskHashMap) idTable).close(); } } public void save() throws Exception { } public DxIterator objectIDIterator() { return idTable.iterator(); } protected void commitNameTable() throws IOException { env.logWriter.newEntry(this, "commitNameTable...", LogWriter.DEBUG3); String filename = env.getDatabaseDir() + NAME_TABLE_NAME; ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename)); try { out.writeInt(nameTable.count()); DxIterator it = nameTable.iterator(); while (it.next() != null) { out.writeObject(it.object()); out.writeObject(it.key()); } } catch (Exception e) { new File(filename).delete(); } finally { out.close(); } } protected void commitIDTable() throws IOException { env.logWriter.newEntry(this, "commitIDTable...", LogWriter.DEBUG3); if (!(idTable instanceof DxDiskHashMap)) { String filename = env.getDatabaseDir() + ID_TABLE_NAME; ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename)); try { out.writeInt(idTable.count()); DxIterator it = idTable.iterator(); while (it.next() != null) { out.writeObject(it.object()); out.writeObject(it.key()); } } catch (Exception e) { new File(filename).delete(); } finally { out.close(); } } else { ((IDTable) idTable).setReusable(false); ((IDTable) idTable).writeDirtyTables(); ((IDTable) idTable).setReusable(true); } } /** * Fill idTable and nameTable from the information that are stored in the * clusters directly. * * @throws Exception If a cluster cannot be read. */ protected synchronized void recover() throws Exception { env.logWriter.newEntry(this, " cleaning ID table...", LogWriter.INFO); ((DxDiskHashMap) idTable).cleanFiles(); (idTable).clear(); env.logWriter.newEntry(this, " cleaning name table...", LogWriter.INFO); nameTable.clear(); Set cids = clusterStore.recoverClusterIDs(); Set uncommittedTaIDs = clusterStore.uncommittedTaIDs(); int totalNumClusters = cids.size(); int processedNumClusters = 1; for (Iterator it = cids.iterator(); it.hasNext(); ) { ClusterID cid = (ClusterID) it.next(); Cluster cluster = null; boolean exceptionWhileLoading = false; env.logWriter.newEntry(this, " cluster: " + cid + " (" + processedNumClusters++ + " of " + totalNumClusters + ")", LogWriter.INFO); try { cluster = clusterStore.restoreCluster(cid, uncommittedTaIDs); env.logWriter.newEntry(this, " " + cluster.containers().count() + " containers", LogWriter.INFO); } catch (Exception e) { env.logWriter.newEntry(this, "exception while loading cluster: " + cid + " (" + e + ")", LogWriter.WARN); env.logWriter.newEntry(this, "", e, LogWriter.DEBUG); exceptionWhileLoading = true; } if (exceptionWhileLoading || cluster.containers().isEmpty()) { if (exceptionWhileLoading) { env.logWriter.newEntry(this, " unable to read cluster - should be deleted!", LogWriter.INFO); } else { env.logWriter.newEntry(this, " cluster is empty - should be deleted!", LogWriter.INFO); } if (cluster != null) { env.logWriter.newEntry(this, " try to delete cluster...", LogWriter.INFO); cluster.delete(); } } else { // fill in idTable and nameTable DxIterator it2 = cluster.containers().iterator(); StorageObjectContainer container; while ((container = (StorageObjectContainer) it2.next()) != null) { if (env.logWriter.hasTarget(LogWriter.DEBUG)) { if (container.id().value()==1) { env.logWriter.newEntry(this, "Adding container "+container+".", LogWriter.DEBUG); } } if (idTable.addForKey(cluster.clusterID(), container.id()) == false) { throw new IllegalStateException("Unable to add container "+container+" to ID table because cluster ID "+idTable.elementForKey(container.id())+" is already registered for container ID "+container.id()+"."); } if (container.name() != null) { env.logWriter.newEntry(this, " adding name: " + container.name(), LogWriter.INFO); if (nameTable.addForKey(container.id(), container.name()) == false) { throw new IllegalStateException("Unable to add name to name table: " + container.name()); } } } } clusterStore.unloadCluster(cid, false); } commitIDTable(); commitNameTable(); } public synchronized ObjectContainer newContainerAndLock(Transaction ta, OzoneCompatible target, ObjectID objID, Permissions permissions, int lockLevel) throws Exception { StorageObjectContainer container = new MagicObjectContainer(objID); if (target != null) { container.setTarget(target); } clusterStore.registerContainerAndLock(container, permissions, ta, lockLevel); boolean alright = false; try { garbageCollector.notifyNewObjectContainer(container); MagicTransaction transaction = (MagicTransaction) ta; ClusterID cid = container.getCluster().clusterID(); ObjectID oid = container.id(); if (env.logWriter.hasTarget(LogWriter.DEBUG3)) { env.logWriter.newEntry(this, "newContainer(): cid=" + cid + ",oid=" + oid + ".", LogWriter.DEBUG3); } transaction.idTable.addForKey(cid, oid); transaction.idTableChanges_push(new IDTableChange(oid, cid, IDTableChange.STATE_ADDED)); alright = true; return container; } finally { if (!alright) { container.getCluster().lock().release(ta); } } } // public synchronized void deleteContainer (Transaction ta, ObjectContainer _container) // throws Exception { // if (env.logWriter.hasTarget (LogWriter.DEBUG3)) // env.logWriter.newEntry (this, "deleteContainer()", LogWriter.DEBUG3); // // MagicObjectContainer container = (MagicObjectContainer)_container; // taData.idTableChanges.push (new IDTableChange (oid, cid, IDTableChange.STATE_ADDED)); public void updateLockLevel(Transaction _ta, ObjectContainer _container) throws IOException { if (env.logWriter.hasTarget(LogWriter.DEBUG3)) { env.logWriter.newEntry(this, "updateLockLevel()", LogWriter.DEBUG3); } if (_container instanceof StorageObjectContainer) { StorageObjectContainer container = (StorageObjectContainer) _container; container.getCluster().updateLockLevel(_ta); MagicTransaction wizardTa = (MagicTransaction) _ta; wizardTa.idTable.addForKey(container.getCluster().clusterID(), container.id()); } } /** * Returns the ObjectContainer for the given ObjectID or null if there is * no such container.<p> * * @param ta the Transaction for within the container is requested or null. * * Impl. Note: For performance reasons this is the only method of this Store * that is not synchronized. This will not cause problems because the only * field that is updated inside the method (currentContainer) does not need * to be stable while this method is running. */ public ObjectContainer containerForID(Transaction ta, ObjectID id) throws ObjectNotFoundException, IOException, ClassNotFoundException { StorageObjectContainer container = null; MagicTransaction magicTa = (MagicTransaction) ta; MagicTransaction transaction = (MagicTransaction) ta; // search the LRU cluster to speed things up; since this is not // synchronized, checking and accessing currentCluster must be done in // one line to avoid other thread to change the variable in between // container = (currentCluster != null && currentCluster.lock != null) ? currentCluster.containerForID (id) : null; // if (container != null) { // // System.out.print ("+"); // return container.isDeleted() ? null : container; // } ClusterID cid = null; // search members of current ta first if (ta != null) { DxMap taDataIDTable = transaction.idTable; cid = (ClusterID) taDataIDTable.elementForKey(id); if (cid == null && transaction.lrucid != null) { Cluster lru = clusterStore.loadCluster(transaction.lrucid, magicTa); if (lru != null) { container = lru.lock() != null ? lru.containerForID(id) : null; if (container != null) { // System.out.print ("+"); if (container.isDeleted()) { return null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -