package com.neocoretechs.bigsack.io.pooled; import java.io.IOException; import java.io.Serializable; import com.neocoretechs.bigsack.DBPhysicalConstants; /* * Copyright (c) 2003, NeoCoreTechs * All rights reserved. * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * Neither the name of NeoCoreTechs nor the names of its contributors may be * used to endorse or promote products derived from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * Holds the page block buffer for one block. Also contains current * read/write position for block. Controls access and enforces * overwrite rules. Used as entries in buffer pool that have the virtual block number blockNum as key. * We intentionally do not attach a tablespace because these entries can move around at will. * @author Groff */ @SuppressWarnings("rawtypes") public final class BlockAccessIndex implements Comparable, Serializable { private static boolean DEBUG = false; private static final long serialVersionUID = -7046561350843262757L; private Datablock blk; private transient int accesses = 0; private long blockNum = -1L; protected short byteindex = -1; public BlockAccessIndex(boolean init) throws IOException { if(init) init(); } /** This constructor used for setting search templates */ public BlockAccessIndex() { } /** This method can be used for ThreadLocal post-init after using default ctor * @throws IOException if block superceded a block under write or latched * */ public synchronized void init() throws IOException { setBlk(new Datablock(DBPhysicalConstants.DATASIZE)); } public synchronized void resetBlock() { accesses = 0; byteindex = 0; blk.resetBlock(); } public synchronized int getAccesses() { return accesses; } synchronized void addAccess() { ++accesses; //if( accesses > 1 ) { // System.out.println("BlockAccessIndex.addAccess access > 1 "+this); // new Throwable().printStackTrace(); //} } public synchronized int decrementAccesses() throws IOException { if( accesses == 1 && blk.isIncore() ) return accesses; if (accesses > 0 ) --accesses; //else { //if( blk.isIncore() ) { //System.out.println("Accesses to 0 with incore latched:"+this); //new Throwable().printStackTrace(); //} //} return accesses; } public synchronized String toString() { String db = "BlockAccessIndex: "; db += " data " + blk == null ? "null block" : blk.toBriefString() + " accesses:" + accesses + " byteindex:" + byteindex + " inLog:" + blk.isInlog() + "." ; return db; } public synchronized long getBlockNum() { return blockNum; } /** * Set the block number and make sure we are not overwriting a previous entry that is active. * It should have 1 access, it should not be incore or in the log. Setting an invalid block also fails assertion * @param bnum * @throws IOException */ public synchronized void setBlockNumber(long bnum) throws IOException { assert (bnum != -1L) : "****Attempt to set block number invalid"; //if( GlobalDBIO.valueOf(bnum).equals("Tablespace_1_114688")) // System.out.println("BlockAccessIndex.setBlockNum. Tablespace_1_114688"); // add an access, latch immediately addAccess(); // We are about to replace the current block, make sure it is not under write or latched by someone else // or we would be trashing data. We already latched it so there should be only 1 if( accesses > 1 ) throw new IOException("****Attempt to overwrite latched block, accesses "+accesses+" for buffer "+this+" with "+bnum); /* if (bnum == blockNum) { byteindex = 0; return; } // If its been written but not yet in log, write it if (blk.isIncore() && !blk.isInlog()) { globalIO.getUlog().writeLog(this); } */ blockNum = bnum; byteindex = 0; /* globalIO.getIOManager().FseekAndRead(blockNum, blk); //if( GlobalDBIO.valueOf(bnum).equals("Tablespace_1_114688")) // System.out.println("BlockAccessIndex.setBlockNum. Tablespace_1_114688"+this+" "+blk.blockdump()); assert(blk.getBytesinuse() > 0 && blk.getBytesused() > 0) : "BlockAccessIndex.setBlockNum unusable block returned from read at "+GlobalDBIO.valueOf(blockNum)+" "+blk.blockdump(); */ } @Override public synchronized int compareTo(Object o) { if (blockNum < ((BlockAccessIndex) o).blockNum) return -1; if (blockNum > ((BlockAccessIndex) o).blockNum) return 1; return 0; } @Override public synchronized boolean equals(Object o) { return (blockNum == ((BlockAccessIndex) o).blockNum); } /** * If the buffers are per tablespace and we are below 4 gig this should be unique * and offer optimum distribution */ @Override public synchronized int hashCode() { return (int) (0xFFFFFFFF & blockNum); } public synchronized Datablock getBlk() { return blk; } /** * Set the presumably latched blockaccessindex with the datablock of data. * Check to make sure the previous block is not in danger * @param blk */ public synchronized void setBlk(Datablock blk) throws IOException { // blocks not same and not first, check for condition of the block we are replacing if( blk.isIncore() ) throw new IOException("****Attempt to overwrite block in core for buffer "+this); blk.setIncore(false); blk.setInlog(false); // We are about to replace the current block, make sure it is not under write or latched by someone else // or we would be trashing data. We already latched it so there should be only 1 if( accesses > 1 ) throw new IOException("****Attempt to overwrite latched block, accesses "+accesses+" for buffer "+this); this.blk = blk; } public synchronized short getByteindex() { return byteindex; } public synchronized short setByteindex(short byteindex) { this.byteindex = byteindex; return byteindex; } }