Package com.trifork.bitcask

Source Code of com.trifork.bitcask.BitCaskLock

/**
* This file is part of Bitcask Java
*
* Copyright (c) 2011 by Trifork
*
* 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.trifork.bitcask;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;

import com.google.protobuf.ByteString;

public class BitCaskLock {

  public static enum Stale {
    OK, NOT_STALE
  }

  public static enum Type {
    WRITE, MERGE;

    private  String type_name() {
      if (this == MERGE) return "merge";
      if (this == WRITE) return "write";
      throw new RuntimeException();
    }
  }

  private RandomAccessFile file;
  private boolean is_write_lock;
  private File filename;

  private BitCaskLock(RandomAccessFile file, File filename, boolean isWriteLock) {
    this.file = file;
    this.filename = filename;
    this.is_write_lock = isWriteLock;
  }


  public static File read_activefile(Type type, File dirname) {
    File lock_filename = lock_filename(type, dirname);
    try {
      BitCaskLock lock = lock_acquire(lock_filename, false);

      try {
      String contents = lock.read_lock_data();
     
      int idx = contents.indexOf(' ');
      if (idx != -1) {
        String rest = contents.substring(idx + 1);
       
        int end = rest.indexOf('\n');
        if (end != -1) {
          String path = rest.substring(0, end);
          return new File(path);
        }
      }
     
      } finally {
        lock.release();
      }
     
    } catch (Exception e) {
    }

    return null;

  }

  public void write_activefile(Type type, File dirname) throws IOException {
    write_activefile(lock_filename(type, dirname));
  }
   
  public void write_activefile(BitCaskFile file) throws IOException {
    write_activefile(file.filename);
  }
   
  private void write_activefile(File activeFilename) throws IOException {
   
    String lock_contents =
      Integer.toString(OS.getpid()) + " " + activeFilename.getPath() + "\n";
    write_data(ByteString.copyFromUtf8(lock_contents));
   
  }
 
  public static BitCaskLock acquire(Type type, File dirname) throws IOException {
    File lock_filename = lock_filename(type, dirname);
    foo: do {
      try {
        BitCaskLock lock = lock_acquire(lock_filename, true);

        String lock_contents = Integer.toString(OS.getpid()) + " \n";
        lock.write_data(ByteString.copyFromUtf8(lock_contents));

        return lock;

      } catch (FileAlreadyExistsException e) {
        delete_stale_lock(lock_filename);
        continue foo;
      }
    } while (false);

    return null;
  }

  private void write_data(ByteString bytes) throws IOException {
    FileChannel ch = file.getChannel();
    if (is_write_lock) {
      ch.truncate(0);
      ch.write(bytes.asReadOnlyByteBuffer(), 0);

      return;
    }

    throw new IOException("file not writable");
  }

  public static Stale delete_stale_lock(Type type, File dirname) throws IOException {
    return delete_stale_lock(lock_filename(type, dirname));
  }
 
  private static Stale delete_stale_lock(File lockFilename) throws IOException {

    BitCaskLock l = null;

    try {
      l = lock_acquire(lockFilename, false);

    } catch (FileNotFoundException e) {
      return Stale.OK;
    } catch (IOException e) {
      return Stale.NOT_STALE;
    }

    try {

      int pid = l.read_lock_data_pid();

      if (OS.pid_exists(pid)) {
        return Stale.NOT_STALE;
      } else {
        lockFilename.delete();
        return Stale.OK;
      }

    } catch (IOException e) {
      return Stale.NOT_STALE;
    } finally {
      l.release();
    }

  }

  private int read_lock_data_pid() throws IOException {
    String data = read_lock_data();

    int idx = data.indexOf(' ');
    if (idx != -1) {
      return Integer.parseInt(data.substring(0, idx));
    }
   
    throw new IOException();
  }

  private String read_lock_data() throws IOException {
    this.file.seek(0);
    int len = (int) file.length();
    byte[] data = new byte[len];
    file.read(data);

    ByteString s = ByteString.copyFrom(data);
    String ss = s.toStringUtf8()
   
    return ss;
  }

  public void release() throws IOException {
    if (file != null) {

      if (is_write_lock) {
        file.close();
        filename.delete();
      }
    }

    file = null;
  }

  private static BitCaskLock lock_acquire(File lockFilename, boolean is_write_lock)
      throws IOException {

    if (is_write_lock) {
      if (lockFilename.createNewFile() == false) {
        // file already exists, so we fail!

        throw new FileAlreadyExistsException(lockFilename);
      }
    }

    RandomAccessFile f = new RandomAccessFile(lockFilename,
        is_write_lock ? "rws" : "r");

    return new BitCaskLock(f, lockFilename, is_write_lock);
  }

  private static File lock_filename(Type type, File dirname) {
    return new File(dirname, "bitcask." + type.type_name() + ".lock");
  }

}
TOP

Related Classes of com.trifork.bitcask.BitCaskLock

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.