blob: 1b8bc156460b9fe7f4d20231401c3d17965524c1 [file] [log] [blame]
/*
* Copyright 2009-2010 by The Regents of the University of California
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may obtain a copy of the License from
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.uci.ics.hyracks.storage.am.common.frames;
import java.nio.ByteBuffer;
import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
// all meta pages of this kind have a negative level
// the first meta page has level -1, all other meta pages have level -2
// the first meta page is special because it guarantees to have a correct max page
// other meta pages (i.e., with level -2) have junk in the max page field
public class LIFOMetaDataFrame implements ITreeIndexMetaDataFrame {
// Arbitrarily chosen magic integer.
protected static final int MAGIC_VALID_INT = 0x5bd1e995;
protected static final int tupleCountOff = 0; //0
protected static final int freeSpaceOff = tupleCountOff + 4; //4
protected static final int maxPageOff = freeSpaceOff + 4; //8
protected static final int levelOff = maxPageOff + 12; //20
protected static final int nextPageOff = levelOff + 1; // 21
protected static final int validOff = nextPageOff + 4; // 25
protected static final int lsnOff = validOff + 4; // 29
protected ICachedPage page = null;
protected ByteBuffer buf = null;
public int getMaxPage() {
return buf.getInt(maxPageOff);
}
public void setMaxPage(int maxPage) {
buf.putInt(maxPageOff, maxPage);
}
public int getFreePage() {
int tupleCount = buf.getInt(tupleCountOff);
if (tupleCount > 0) {
// return the last page from the linked list of free pages
// TODO: this is a dumb policy, but good enough for now
int lastPageOff = buf.getInt(freeSpaceOff) - 4;
buf.putInt(freeSpaceOff, lastPageOff);
buf.putInt(tupleCountOff, tupleCount - 1);
return buf.getInt(lastPageOff);
} else {
return -1;
}
}
// must be checked before adding free page
// user of this class is responsible for getting a free page as a new meta
// page, latching it, etc. if there is no space on this page
public boolean hasSpace() {
return buf.getInt(freeSpaceOff) + 4 < buf.capacity();
}
// no bounds checking is done, there must be free space
public void addFreePage(int freePage) {
int freeSpace = buf.getInt(freeSpaceOff);
buf.putInt(freeSpace, freePage);
buf.putInt(freeSpaceOff, freeSpace + 4);
buf.putInt(tupleCountOff, buf.getInt(tupleCountOff) + 1);
}
@Override
public byte getLevel() {
return buf.get(levelOff);
}
@Override
public void setLevel(byte level) {
buf.put(levelOff, level);
}
@Override
public ICachedPage getPage() {
return page;
}
@Override
public void setPage(ICachedPage page) {
this.page = page;
this.buf = page.getBuffer();
}
@Override
public void initBuffer(byte level) {
buf.putInt(tupleCountOff, 0);
buf.putInt(freeSpaceOff, lsnOff + 4);
//buf.putInt(maxPageOff, -1);
buf.put(levelOff, level);
buf.putInt(nextPageOff, -1);
setValid(false);
}
@Override
public int getNextPage() {
return buf.getInt(nextPageOff);
}
@Override
public void setNextPage(int nextPage) {
buf.putInt(nextPageOff, nextPage);
}
@Override
public boolean isValid() {
return buf.getInt(validOff) == MAGIC_VALID_INT;
}
@Override
public void setValid(boolean isValid) {
if (isValid) {
buf.putInt(validOff, MAGIC_VALID_INT);
} else {
buf.putInt(validOff, 0);
}
}
@Override
public long getLSN() {
return buf.getLong(lsnOff);
}
@Override
public void setLSN(long lsn) {
buf.putLong(lsnOff, lsn);
}
}