Package com.google.code.fqueue.log

Source Code of com.google.code.fqueue.log.LogIndex

/*
*  Copyright 2011 sunli [sunli1223@gmail.com][weibo.com@sunli1223]
*
*  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 at
*
*      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 com.google.code.fqueue.log;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.code.fqueue.exception.FileFormatException;

/**
* 数据索引文件
*
* @author sunli
* @date 2011-5-18
* @version $Id: LogIndex.java 2 2011-07-31 12:25:36Z sunli1223@gmail.com $
*/
public class LogIndex {
  final Logger log = LoggerFactory.getLogger(LogIndex.class);
  private final int dbFileLimitLength = 32;
  private RandomAccessFile dbRandFile = null;
  private FileChannel fc;
  private MappedByteBuffer mappedByteBuffer;

  /**
   * 文件操作位置信息
   */
  private String magicString = null;
  private int version = -1;
  private int readerPosition = -1;
  private int writerPosition = -1;
  private int readerIndex = -1;
  private int writerIndex = -1;
  private AtomicInteger size = new AtomicInteger();

  public LogIndex(String path) throws IOException, FileFormatException {
    File dbFile = new File(path);

    // 文件不存在,创建文件
    if (dbFile.exists() == false) {
      dbFile.createNewFile();
      dbRandFile = new RandomAccessFile(dbFile, "rwd");
      dbRandFile.write(LogEntity.MAGIC.getBytes());// magic
      dbRandFile.writeInt(1);// 8version
      dbRandFile.writeInt(LogEntity.messageStartPosition);// 12 reader
      // pos
      dbRandFile.writeInt(LogEntity.messageStartPosition); // 16write
      // pos
      dbRandFile.writeInt(1);// 20readerindex
      dbRandFile.writeInt(1);// 24writerindex
      dbRandFile.writeInt(0);// 28 size
      magicString = LogEntity.MAGIC;
      version = 1;
      readerPosition = LogEntity.messageStartPosition;
      writerPosition = LogEntity.messageStartPosition;
      readerIndex = 1;
      writerIndex = 1;
    } else {
      dbRandFile = new RandomAccessFile(dbFile, "rwd");
      if (dbRandFile.length() < 32) {
        throw new FileFormatException("file format error");
      }
      byte[] b = new byte[this.dbFileLimitLength];
      dbRandFile.read(b);
      ByteBuffer buffer = ByteBuffer.wrap(b);
      b = new byte[LogEntity.MAGIC.getBytes().length];
      buffer.get(b);
      magicString = new String(b);
      version = buffer.getInt();
      readerPosition = buffer.getInt();
      writerPosition = buffer.getInt();
      readerIndex = buffer.getInt();
      writerIndex = buffer.getInt();
      size.set(buffer.getInt());

    }
    fc = dbRandFile.getChannel();
    mappedByteBuffer = fc.map(MapMode.READ_WRITE, 0, this.dbFileLimitLength);
  }

  /**
   * 记录写位置
   *
   * @param pos
   */
  public void putWriterPosition(int pos) {
    mappedByteBuffer.position(16);
    mappedByteBuffer.putInt(pos);
    this.writerPosition = pos;
  }

  /**
   * 记录读取的位置
   *
   * @param pos
   */
  public void putReaderPosition(int pos) {
    mappedByteBuffer.position(12);
    mappedByteBuffer.putInt(pos);
    this.readerPosition = pos;
  }

  /**
   * 记录写文件索引
   *
   * @param index
   */
  public void putWriterIndex(int index) {
    mappedByteBuffer.position(24);
    mappedByteBuffer.putInt(index);
    this.writerIndex = index;
  }

  /**
   * 记录读取文件索引
   *
   * @param index
   */
  public void putReaderIndex(int index) {
    mappedByteBuffer.position(20);
    mappedByteBuffer.putInt(index);
    this.readerIndex = index;
  }

  public void incrementSize() {
    int num = size.incrementAndGet();
    mappedByteBuffer.position(28);
    mappedByteBuffer.putInt(num);
  }

  public void decrementSize() {
    int num = size.decrementAndGet();
    mappedByteBuffer.position(28);
    mappedByteBuffer.putInt(num);
  }

  public String getMagicString() {
    return magicString;
  }

  public int getVersion() {
    return version;
  }

  public int getReaderPosition() {
    return readerPosition;
  }

  public int getWriterPosition() {
    return writerPosition;
  }

  public int getReaderIndex() {
    return readerIndex;
  }

  public int getWriterIndex() {
    return writerIndex;
  }

  public int getSize() {
    return size.get();
  }

  /**
   * 关闭索引文件
   */
  public void close() {
    try {
      mappedByteBuffer.force();
      AccessController.doPrivileged(new PrivilegedAction<Object>() {
        public Object run() {
          try {
            Method getCleanerMethod = mappedByteBuffer.getClass().getMethod("cleaner", new Class[0]);
            getCleanerMethod.setAccessible(true);
            sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod.invoke(mappedByteBuffer,
                new Object[0]);
            cleaner.clean();
          } catch (Exception e) {
            log.error("close logindexy file error:", e);
          }
          return null;
        }
      });
      fc.close();
      dbRandFile.close();
      mappedByteBuffer = null;
      fc = null;
      dbRandFile = null;
    } catch (IOException e) {
      log.error("close logindex file error:", e);
    }
  }

  public String headerInfo() {
    StringBuilder sb = new StringBuilder();
    sb.append(" magicString:");
    sb.append(magicString);
    sb.append(" version:");
    sb.append(version);
    sb.append(" readerPosition:");
    sb.append(readerPosition);
    sb.append(" writerPosition:");
    sb.append(writerPosition);
    sb.append(" size:");
    sb.append(size);
    sb.append(" readerIndex:");
    sb.append(readerIndex);
    sb.append(" writerIndex:");
    sb.append(writerIndex);
    return sb.toString();
  }

}
TOP

Related Classes of com.google.code.fqueue.log.LogIndex

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.