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

📄 blockfile.java

📁 实现数据库的storage manager 功能
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
    writeBlock(b, currentBlock);
  }
  
  /**
   * Write to the specified logical position.
   *
   * @param b the bytes to be written.
   * @param blockNo the logical index.
   * @exception IOException if physical writing fails.
   */
  public void writeBlock(byte[] b, int blockNo) throws IOException{
    writePhysicalBlock(b, pointers[blockNo]);
  }

  /**
   * Write to the specified physical postion.
   *
   * @param b the bytes to be written.
   * @param blockNo the logical index.
   * @exception IOException if physical writing fails.
   */
  public void writePhysicalBlock(byte[] b, int blockNo) throws IOException{
    /*if(fileCache != null){
      fileCache.put(new Integer(blockNo), b);
      return;
      }*/
    file.seek(blockNo * blockSize);
    file.write(b);
    writeOps++;
  }

  /**
   * Read the next logical block from the current block index.
   *
   * @return an array of bytes.
   * @exception IOException if physical reading fails.
   */
  public byte[] readNextBlock() throws IOException{
    if(currentBlock < numBlocks)
      return readBlock(currentBlock + 1);
    else
      return null;
  }

  /**
   * Read the previous logical block from the current block index.
   *
   * @return an array of bytes.
   * @exception IOException if physical reading fails.
   */
  public byte[] readPreviousBlock() throws IOException{
    if(currentBlock == 0)
      return null;
    return readBlock(currentBlock - 1);
  }

  
  /**
   * Insert a new block after the specified logical index. So if the
   * specified index is 0 a the new block will have the logcial index
   * of 1. To insert a block at the first logical position in the file
   * use -1.
   *
   * @param blockNo the previous index of the current block.
   * @exception IOException if physical writing fails.
   */
  public void insertBlock(int blockNo) throws IOException{
    try{
      currentBlock = blockNo + 1;
      highBlock += 1;
      //System.out.println("new length: "+file.length()+" "+blockSize);
      //file.setLength(file.length() + blockSize);
      numBlocks++;
      
      if((numBlocks) ==  pointers.length - 1){ //we have to grow the pointers
	System.out.println("growing pointers");
	short[] tmp = new short[pointers.length * 2];
	System.arraycopy(pointers, 0, tmp, 0, pointers.length);
	pointers = tmp;
      }
      if(currentBlock == numBlocks)
	pointers[currentBlock] = highBlock;
      else
	System.arraycopy(pointers, currentBlock, pointers, currentBlock + 1, numBlocks - blockNo);
      
      pointers[currentBlock] = highBlock;
    }
    catch(Exception e){
      System.out.println(pointers.length+" "+currentBlock+" "+numBlocks+" "+blockNo);
      throw new IOException(e.toString());
    }
  }

  
  /**
   * Remove the specified block from the file. It is only the logical reference that
   * will be unlinked, i.e. the method does not fill the block with zeros or something.
   * Also note that the physical space will be unavailable to new blocks until a
   * defragment has been issued.
   *
   * @param blockNo the logical block to delete
   * @see BlockFile#defragment()
   */
  public void removeBlock(int blockNo){
    /*if(fileCache != null)
      fileCache.remove(new Integer(pointers[blockNo]));
    */
    if(numBlocks-1 == 0){
      System.out.println("Removing all data");
      try{
	file.setLength(0);
      }
      catch(IOException e){System.out.println(e);}
      pointers = new short[256];
      currentBlock = -1;
      numBlocks = 0;
      highBlock = -1;
      return;
    }
    System.arraycopy(pointers, blockNo + 1, pointers, blockNo, numBlocks - blockNo + 1);
    numBlocks--;
  }

  /**
   * Prints header information of the block file and the logical and physical mapping.
   */
  public String toString(){
    StringBuffer sbuff = new StringBuffer();
    sbuff.append("File name: "+fileName+'\n');
    sbuff.append("Block size: "+blockSize+'\n');
    sbuff.append("Num blocks: "+numBlocks+'\n');
    sbuff.append("Highest logical block: "+highBlock+'\n');
    sbuff.append("block capacity: "+pointers.length+'\n');
    sbuff.append("Logical and physical block order: ");
    for(int i = 0; i < numBlocks; i++){
      sbuff.append(i+":"+pointers[i]+" ");
    }
    sbuff.append('\n');
    return sbuff.toString();
  }
  
  
  /**
   * The defragment removes unused space and remapps the logical/physical 
   * mapping so that the logical block 0 will be the first block in the file, 
   * and so on.
   *
   * @exception IOException if physical read/write fails.
   */
  public void defragment() throws IOException{
    //writeHeader();
    /*if(fileCache != null)
      fileCache.emptyCache();
    */
    RandomAccessFile raf = new RandomAccessFile("defragment.tmp", "rw");
    RandomAccessFile raf1 = new RandomAccessFile("defragment_pointers.tmp", "rw");
    synchronized(file){
      int i;
      for(i = 0; i < numBlocks; i++){
	raf.write(readBlock(i));
	
      }
      raf.close();

      //now write the header:
      //byte hBlock[] = new byte[18 + (numBlocks * 2)];
      //ByteStorage.writeInt(hBlock, 0, numBlocks);
      //ByteStorage.writeInt(hBlock, 4, currentBlock);
      //ByteStorage.writeInt(hBlock, 8, pointers.length);
      //ByteStorage.writeInt(hBlock, 12, blockSize);
      //ByteStorage.writeShort(hBlock, 16, (short) (numBlocks - 1));

      //Write header:
      ByteBuffer bb = ByteBuffer.allocate(18 + (numBlocks * 2));
      bb.putInt(numBlocks);
      bb.putInt(currentBlock);
      bb.putInt(pointers.length);
      bb.putInt(blockSize);
      bb.putShort((short) (numBlocks -1));

      for(i = 0; i < numBlocks; i++){
	bb.putShort((short) i);
      }
      bb.flip();
      raf1.getChannel().write(bb);
      raf1.close();
      file.close();

      File f = new File(fileName+BLOCK_FILE_EXTENSION);
      f.delete();
      File f1 = new File("defragment.tmp");
      f1.renameTo(f);
  
      f = new File(fileName+POINTER_FILE_EXTENSION);
      f.delete();
      f1 = new File("defragment_pointers.tmp");
      f1.renameTo(f);
      openFile();
    }
    
  }
  
  
  /**
   * Tries to close the file if it is open
   *
   */
  protected void finalize(){
    try{
      closeFile();
    }
    catch(IOException e){System.out.println(e);}
  }

  /********************PRIVATE SECTION*****************************************/
  private void writeHeader() throws IOException{
    RandomAccessFile raf = new RandomAccessFile(fileName + POINTER_FILE_EXTENSION, "rw");
    ByteBuffer bb = ByteBuffer.allocate(18 + (numBlocks * 2));
    bb.putInt(numBlocks);
    bb.putInt(currentBlock);
    bb.putInt(pointers.length);
    bb.putInt(blockSize);
    bb.putShort(highBlock);
    for(int i = 0; i < numBlocks; i++){
      bb.putShort((short) pointers[i]);
    }
    bb.flip();
    raf.getChannel().write(bb);
    raf.close();
  }

  private void createFile() throws IOException{
    file = new RandomAccessFile(fileName+BLOCK_FILE_EXTENSION, "rw");
    file.setLength(0);
    currentBlock = -1;
    numBlocks = 0;
    highBlock = -1;
  }

  private void openFile() throws IOException{
    //read the pointers:
    RandomAccessFile raf = new RandomAccessFile(fileName + POINTER_FILE_EXTENSION, "r");
    ByteBuffer bb = ByteBuffer.allocate((int) raf.length());
    raf.getChannel().read(bb);
    bb.flip();
    numBlocks = bb.getInt();
    currentBlock = bb.getInt();
    pointers = new short[bb.getInt()];
    blockSize = bb.getInt();
    highBlock = bb.getShort();
    for(int i = 0; i < numBlocks; i++)
      pointers[i] = bb.getShort();
    
    raf.close();
    //open block file:
    file = new RandomAccessFile(fileName+BLOCK_FILE_EXTENSION, "rw");
  }


  /*********************************INNER CLASSES**************************/
  class BFIterator implements Iterator{
    int count = numBlocks;
    int cursor = 0;
    int lastRet = -1;

    public BFIterator(int blockNo, boolean logical){
      cursor = (logical)?blockNo:getLogicalBlockNo(blockNo);
      if(cursor < 0) //the physical blockNo did not exsist
	cursor = numBlocks+10;
    }

    public BFIterator(){
      ;
    }

    public boolean hasNext(){
      return (cursor < numBlocks);
    }
    
    public Object next(){
      try{
	check();
	if(cursor >= numBlocks)
	  throw new NoSuchElementException();
	
	Object block = readBlock(cursor);
	lastRet = cursor++;
	return block;
      }
      catch(IOException e){
	throw new NoSuchElementException();
      }
      
    }

    public void remove(){
      if(lastRet == -1)
	throw new IllegalStateException();
      check();
      removeBlock(lastRet);
      if(lastRet < cursor)
	cursor--;
      lastRet = -1;
      count = numBlocks;
    }

    private void check(){
      if(count != numBlocks)
	throw new ConcurrentModificationException();
    }
  }
  
  /*
  class Callback implements CacheCallback{
    public void remove(Object key, Object value){
      try{
	file.seek(((Integer)key).intValue() * blockSize);
	file.write((byte[])value);
	writeOps++;
      }
      catch(IOException e){
	System.out.println(e);
      }
    }
  }
  */
}

⌨️ 快捷键说明

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