📄 dxdiskhashmap.java
字号:
// You can redistribute this software and/or modify it under the terms of// the Ozone Library 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: DxDiskHashMap.java,v 1.16 2004/01/27 21:51:54 wieslawf Exp $package org.ozoneDB.DxLib;import org.ozoneDB.io.stream.ResolvingObjectInputStream;import java.io.*;import java.util.Arrays;/** * @author <a href="http://www.softwarebuero.de/">SMB</a> * @author <a href="http://www.medium.net/">Medium.net</a> * @version $Revision: 1.16 $Date: 2004/01/27 21:51:54 $ */public class DxDiskHashMap extends DxAbstractMap { final static long serialVersionUID = 2; public final static String ROOT_TABLE_NAME = ".rootTable"; private String baseFileName; /** The directory where all tables reside. */ protected File tableDirectory; private long subTableNameCount = System.currentTimeMillis(); private DxDiskSubTable rootTable; private int itemCount = 0; private int[] tableBitSizes = new int[] {8, 8, 8, 8}; // cache related stuff private int cacheBits = 10; private int cacheMask; private DxKeyData[] cache; // buffer related stuff protected int maxBufferSize = 10; protected DxSet buffer; public int bufferAccesses; public int bufferHits; public int cacheAccesses; public int cacheHits; // old tables hashMask bit shift private int oldTablesHashMaskShift; public DxDiskHashMap( String _baseFileName, int _maxBufferSize, int _cacheBits, int[] _tableBitSizes ) { if (_tableBitSizes != null) { if (_tableBitSizes.length == 1) { if (_tableBitSizes[0] < 8 || _tableBitSizes[0] > 16) { throw new RuntimeException( "Illegal tableBitSize value, it should be from 8 to 16." ); } int tbs = _tableBitSizes[0]; int len = 32 / tbs + (32 % tbs > 0 ? 1 : 0); tableBitSizes = new int[len]; Arrays.fill( tableBitSizes, tbs ); if (32 % tbs > 0) { tableBitSizes[tableBitSizes.length-1] = 32 % tbs; } } else { int size = 0; for (int i = 0; i < _tableBitSizes.length; i++) { size += _tableBitSizes[i]; } if (size != 32) { throw new RuntimeException( "Illegal tableBitSize values, the summary bit size must be equal 32." ); } tableBitSizes = _tableBitSizes; } } baseFileName = _baseFileName; maxBufferSize = _maxBufferSize; int index = baseFileName.lastIndexOf(File.separatorChar); if (index != -1) { tableDirectory = new File(baseFileName.substring(0, index) ); } else { tableDirectory = new File(System.getProperty("user.dir",".")); } cacheBits = _cacheBits; cacheMask = (1 << cacheBits) - 1; clear(); } public DxDiskHashMap( String _baseFileName, int _maxBufferSize, int _cacheBits, int _tableBitSize ) { this( _baseFileName, _maxBufferSize, _cacheBits, new int[] {_tableBitSize} ); } public synchronized void clear() { cache = new DxKeyData[1 << cacheBits]; rootTable = new DxDiskSubTable( this, 0 ); buffer = new DxHashSet(); buffer.add( rootTable ); } public DxDiskSubTable rootTable() { return this.rootTable; } public DxDiskHashNodeLeaf newNodeLeaf() { return new DxDiskHashNodeLeaf( this ); } public DxDiskHashNodeBranch newNodeBranch() { return new DxDiskHashNodeBranch( this ); } public DxKeyData newKeyData() { return new DxKeyData(); } public boolean isDirtyTable( DxDiskSubTable table ) { // in general we don't know if and when the data objects stored in // this table has been changed since last write, so we have to assume // it is always dirty return true; } /** * Reuse an existing table from disk. To do so a previously created table * has to be correctly closed. Once a hash map has been re-used it has to * closed before opening again. */ public synchronized void re_use() throws Exception { File f = new File( baseFileName + ROOT_TABLE_NAME ); ObjectInputStream in = new ResolvingObjectInputStream( new BufferedInputStream( new FileInputStream( f ) ) ); try { itemCount = in.readInt(); rootTable.readExternal( in ); rootTable.grandParent = this; buffer.clear(); cache = new DxKeyData[1 << cacheBits]; rootTable.fetchTable(); // update main tableBitSizes array if (rootTable.maxDepth() != tableBitSizes.length-1) { tableBitSizes = new int[rootTable.maxDepth() + 1]; } tableBitSizes[0] = rootTable.bitSize(); DxDiskSubTable subTable = rootTable; while (!subTable.isLeaf()) { DxDiskHashNode[] nodes = subTable.table(); for (int i = 0; i < nodes.length; i++) { if (nodes[i] instanceof DxDiskHashNodeBranch) { subTable = ((DxDiskHashNodeBranch)nodes[i]).subTable; subTable.fetchTable(); tableBitSizes[subTable.depth()] = subTable.bitSize(); break; } } } // calculate hashMask bit shift for old tables // it handles all old table configurations int mask = rootTable.hashMask(); int maskBitSize = 0; while ((mask & 0x80000000) != 0) { maskBitSize++; mask <<= 1; } oldTablesHashMaskShift = rootTable.bitSize() - maskBitSize; } finally { in.close(); } } /** * Close this hash map. Write all changed tables to the disk. Store also * all information that are needed to re-initialize this object from the * disk data. */ public synchronized void close() throws Exception { writeAllTables(); setReusable( true ); } public void setReusable( boolean flag ) throws IOException { File f = new File( baseFileName + ROOT_TABLE_NAME ); if (flag) { ObjectOutputStream out = new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream( f ) ) ); try { out.writeInt( itemCount ); rootTable.writeExternal( out ); } finally { out.close(); } } else { if (f.exists() && !f.delete()) { throw new IOException( "Unable to delete file." ); } } } public Object clone() { throw new RuntimeException( getClass().getName() + ".clone() is not implemented yet." ); } private final Object cachedElementForKey( Object key, int hashCode ) { cacheAccesses++; if (cacheMask == 0) { return null; } int cacheIndex = hashCode & cacheMask; DxKeyData entry = cache[cacheIndex]; if (entry != null && (entry.key == key || entry.key.equals( key ))) { // System.out.print ("."); cacheHits ++; return entry.data; } else { return null; } } private final void addElementToCache( Object obj, Object key, int hashCode ) { if (cacheMask == 0) { return; } synchronized (cache) { int cacheIndex = hashCode & cacheMask; DxKeyData entry = cache[cacheIndex]; if (entry != null) { entry.set( key, obj ); } else { entry = newKeyData(); entry.set( key, obj );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -