package com.lts.kv.data;

import com.lts.kv.AbstractFileHeader;

import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 文件头部
 * 1. magic             2 byte
 * 2. fileLength            4 byte      // 文件的长度
 * 3. totalNum              4 byte      // 总的记录数
 * 4. aliveNum              4 byte      // 存活的记录数
 * 5. isFull                4 byte      // 是否满了 1:满了 0 没满
 * 6. storeTxLogPosition    8 byte      // 刷盘到的最后一条事务日志ID
 * <p/>
 *
 * @author Robert HG (254963746@qq.com) on 12/17/15.
 */
public class DataBlockFileHeader extends AbstractFileHeader {

    // 2 byte
    private final static short magic = (short) 0xBE01;
    // 8 byte       (文件长度)
    private long fileLength;
    // 4 byte       (这个Block总的记录个数)
    private AtomicInteger totalNum = new AtomicInteger(0);
    // 4 byte       (这个Block存活的记录个数)
    private AtomicInteger aliveNum = new AtomicInteger(0);
    // 4 byte       (0:没满 , 1:满了)
    private int isFull;
    // 8 byte       (最后的一个txLog的记录ID)
    private long storeTxLogRecordId;

    @Override
    public int getLength() {
        return 2 + 8 + 4 + 4 + 4 + 8;
    }


    public long getFileLength() {
        return fileLength;
    }

    public void setFileLength(long fileLength) {
        this.fileLength = fileLength;
    }

    public AtomicInteger getTotalNum() {
        return totalNum;
    }

    public void setTotalNum(int totalNum) {
        this.totalNum.set(totalNum);
    }

    public AtomicInteger getAliveNum() {
        return aliveNum;
    }

    public void setAliveNum(int aliveNum) {
        this.aliveNum.set(aliveNum);
    }

    public boolean isFull() {
        return isFull == 1;
    }

    public void markFull() {
        this.isFull = 1;
    }

    public int getIsFull() {
        return isFull;
    }

    public void setIsFull(int isFull) {
        this.isFull = isFull;
    }

    public long getStoreTxLogRecordId() {
        return storeTxLogRecordId;
    }

    public void setStoreTxLogRecordId(long storeTxLogRecordId) {
        this.storeTxLogRecordId = storeTxLogRecordId;
    }

    @Override
    public void read(FileChannel fileChannel) throws IOException {

        fileChannel.position(0);
        fileChannel.read(byteBuffer());

        byteBuffer().position(0);
        short readMagic = byteBuffer().getShort();
        if (readMagic != magic) {
            throw new IOException("Invalid file type magic number 0x" + Integer.toHexString(readMagic & 0xFFFF));
        }

        this.fileLength = byteBuffer().getLong();
        this.totalNum.set(byteBuffer().getInt());
        this.aliveNum.set(byteBuffer().getInt());
        this.isFull = byteBuffer().getInt();
        this.storeTxLogRecordId = byteBuffer().getLong();
    }

    @Override
    public void write(FileChannel fileChannel) throws IOException {

        byteBuffer().position(0);
        byteBuffer().putShort(magic);
        byteBuffer().putLong(fileLength);
        byteBuffer().putInt(totalNum.get());
        byteBuffer().putInt(aliveNum.get());
        byteBuffer().putInt(isFull);
        byteBuffer().putLong(storeTxLogRecordId);
        byteBuffer().flip();

        fileChannel.position(0);
        fileChannel.write(byteBuffer());
        fileChannel.force(true);
    }

}
