⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bufferaccess.java

📁 一个用java编写的从底层开始设计的小型数据库管理系统
💻 JAVA
字号:
package buffer;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import diskaccess.DiskManagement;



/**
 * 块缓冲池--采用时钟算法(LRU的近似算法)管理块
 * 原理
 * 首先构造对象池、设置池的大小
 * 当把新的对象放入到池中时候,池已经满,那把删除最久没有被使用的对象,然后放入对象
 * 当从池中读取对象时候,根据条件从池中获得对象;
 * 然后把池的指针指向该取出的对象,以表明该对象最近最短被使用过
 * @author zh
 */

public class BufferAccess {
	/**
	 * 缓冲池大小,56MB
	 */
	public static final int cacheSize = 16 * 1024 * 1024 / DiskManagement.BLOCK_SIZE;
	
	private static BufferAccess bufferAccessInstance = null;
	
    private DiskManagement diskManagement;
    
    /**
     * 锁住的关键块,只在文件打开时放入,文件关闭时取出
     * 存放mata, schema, index block, index info block
     */
    private Set LockedBlockSet = new HashSet();
    
    /**
     * 块缓冲池,load factor 0.75,确保没有rehash发生
     * 方便起见,只存DataBlock
     */
    private Map blockCache = new HashMap( (int)(cacheSize / 0.75));
    
    /**
     * 时钟算法的环中的当前元素,下一个元素才是淘汰候选对象
     */
    private DataBlock lastUsedBlock;
	 
	private BufferAccess() {
		this.diskManagement = DiskManagement.getInstance();
	}
	
	public static BufferAccess getInstance() {
		if (bufferAccessInstance == null) {
			bufferAccessInstance = new BufferAccess();
		}
		return bufferAccessInstance;
	}
	
	/**
	 * 从buffer中得到一个数据块
	 * @param fileID
	 * @param blockID
	 * @return
	 */
	public DataBlock getBlock(Integer fileID, int blockID ) {
		IDEntry id = new IDEntry(fileID, blockID);
		
		DataBlock block = (DataBlock)blockCache.get(id);
		
		if (block != null) {
		    block.keepNextTurn = true;
			return block;
		}
		
		byte[] blockByte = diskManagement.readFromDisk(fileID, blockID);
		block = new DataBlock(blockByte, id);

		ensureSpace();
		addBlock(block);
		blockCache.put(id, block);
		return block;
	}
	
	void reloadDataBlock(DataBlock nullBlock) {
	    IDEntry id = nullBlock.getIdEntry();
	    DataBlock block = (DataBlock)blockCache.get(id);

	    // 内存中没有相同id的块
	    if (block == null) {
			byte[] blockByte = diskManagement.readFromDisk(id.getFileID(), id.getBlockID());
			ensureSpace();
			
			nullBlock.setData(blockByte);
			addBlock(nullBlock);
			blockCache.put(id, nullBlock);
	        return;
        }
        // 内存中存在相同id的块,需要用到identical指针
	    nullBlock.setData(block.getData());
	    nullBlock.identical = block.identical;
	    block.identical = nullBlock;
	}
	
	/**
	 * 得到一个锁住的块,该块不参与LRU算法的竞争
	 * 只可能是MetaBlock,SchemaBlock,IndexBlock
	 * @param fileID
	 * @param blockID
	 * @param blockType
	 * @return
	 */
	public Block getLockedBlock(Integer fileID, int blockID, int blockType) {
		IDEntry id = new IDEntry(fileID, blockID);
		
		Block block = null;
		
		byte[] blockByte = diskManagement.readFromDisk(fileID, blockID);
		switch (blockType) {
			case Block.META_BLOCK:
				block = new MetaBlock( blockByte, id);
				break;
			case Block.SCHEMA_BLOCK:
				block = new SchemaBlock( blockByte, id);
				break;
			case Block.INDEX_BLOCK:
				block = new IndexBlock( blockByte, id);
				break;
			case Block.INDEX_INFO_BLOCK:
				block = new IndexInfoBlock( blockByte, id);
				break;
			default:
				System.out.println(" illegal block type argument ");
		}
		LockedBlockSet.add( block);
		
		return block;
	}
	
	/**
	 * 调度缓冲区,可能需要丢弃老的块
	 * 确保至少有一个空位置
	 */
	private void ensureSpace() {
		if (blockCache.size() == cacheSize) {
		    lastUsedBlock = lastUsedBlock.next;
		    while (lastUsedBlock.keepNextTurn) {
		        lastUsedBlock.keepNextTurn = false;
		        lastUsedBlock = lastUsedBlock.next;
            }
		    removeBlock(lastUsedBlock);
		}
	}
	
	/**
	 * 在lastUsedElement后加入新元素
	 * @param blk
	 */
	private void addBlock(DataBlock blk) {
		if (lastUsedBlock == null) {
		    blk.next = blk;
		    blk.prev = blk;
		    lastUsedBlock = blk;
		    return;
		}
		
		DataBlock next = lastUsedBlock.next;
		
		lastUsedBlock.next = blk;
		blk.next = next;
		
		blk.prev = lastUsedBlock;
		next.prev = blk;
		
		lastUsedBlock = blk;
	}
	
	/**
	 * 将指定的块删除
	 * 并在必要时改变lastUsedBlcok
	 * @param block
	 */
	private void removeBlock(DataBlock block) {
	    block.prev.next = block.next;
	    block.next.prev = block.prev;
	    blockCache.remove(block.getIdEntry());

	    if (block == lastUsedBlock) {
		    lastUsedBlock = lastUsedBlock == lastUsedBlock.prev ?
		            null : lastUsedBlock.prev;
        }
	    
	    while (block != null) {
		    DataBlock identical = block.identical;
		    block.releaseMemory(diskManagement);
		    block = identical;
        }
    }
	
	/**
	 * 关闭表文件
	 * 将block cache池中特定文件的所有块清空,有必要时写入文件
	 * @param fileID
	 */
	public void closeTableFile(Integer fileID) {
	    Set entrySet = blockCache.entrySet();
	    for (Iterator iter = entrySet.iterator(); iter.hasNext();) {
            Map.Entry entry = (Map.Entry) iter.next();
			if (((IDEntry)entry.getKey()).getFileID().equals(fileID)) {
			    iter.remove();
			    DataBlock block = (DataBlock)entry.getValue();
				removeBlock(block);
				block.releaseMemory(diskManagement);
			}
        }
		diskManagement.closeFile(fileID);
	}
	
	/**
	 * 关闭数据库文件
	 * 将locked block池中特定文件的所有块清空,有必要时写入文件
	 * @param fileID
	 */
	public void closeDBFile(Integer fileID) {
	    for (Iterator iter = LockedBlockSet.iterator(); iter.hasNext();) {
			Block block = (Block) iter.next();
			IDEntry id = block.getIdEntry();
			if (id.getFileID().equals(fileID)) {
				iter.remove();
				block.releaseMemory(diskManagement);
			}
		}
		diskManagement.closeFile(fileID);
	}
	
	/**
	 * @param fileID
	 */
	public void removeTableFile(Integer fileID) {
	    Set entrySet = blockCache.entrySet();
	    for (Iterator iter = entrySet.iterator(); iter.hasNext();) {
            Map.Entry entry = (Map.Entry) iter.next();
			if (((IDEntry)entry.getKey()).getFileID().equals(fileID)) {
			    iter.remove();
			    DataBlock block = (DataBlock)entry.getValue();
				removeBlock(block);
				block.releaseMemory(diskManagement);
			}
        }
		diskManagement.removeFile(fileID);
	}
	
	/**
	 * @return
	 */
	public Integer createFile(String fileName) {
		return diskManagement.createFile(fileName);
	}
	
	/**
	 * @return
	 */
	public Integer createTempFile(String dir, String dbName) {
		return diskManagement.createTempFile(dir, dbName);
	}
	
	/**
	 * @param fileName
	 * @return
	 */
	public Integer loadFile(String fileName) {
		return diskManagement.loadFile(fileName);
	}
	
	/**
	 * @param fileID
	 * @return
	 */
	public int getNewBlockID(Integer fileID) {
		return diskManagement.getNewBlockID(fileID);
	}
	
	/**
	 * @param fileID
	 * @return
	 */
	public int getBlockSize(Integer fileID) {
		return diskManagement.getBlockSize(fileID);
	}
}
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -