com.facebook.infrastructure.db.CommitLogHeader.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.infrastructure.db.CommitLogHeader.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.facebook.infrastructure.db;

import java.io.*;
import java.nio.ByteBuffer;
import java.util.*;
import com.facebook.infrastructure.io.*;
import org.apache.commons.lang.ArrayUtils;

/**
 * Author : Avinash Lakshman ( alakshman@facebook.com) & Prashant Malik ( pmalik@facebook.com )
 */

class CommitLogHeader {
    private static ICompactSerializer<CommitLogHeader> serializer_;

    static {
        serializer_ = new CommitLogHeaderSerializer();
    }

    static ICompactSerializer<CommitLogHeader> serializer() {
        return serializer_;
    }

    static int size(int columnFamilyCount) {
        /* 
         * We serialize the CommitLogHeader as a byte[] and write it
         * to disk. So we first write an "int" to specify the length 
         * of the byte[] which is why we first have a 4 in the sum.
         * We then have size which is the number of bits to track who
         * has been flushed and then the rest is the position[]
         * size = #of column families 
         *        + 
         *        size of the bitset 
         *        + 
         *        size of position array 
         */
        return 4 + columnFamilyCount + (4 * columnFamilyCount);
    }

    static int getLowestPosition(CommitLogHeader clHeader) {
        int[] positions = clHeader.getPositions();
        int minPosition = Integer.MAX_VALUE;
        for (int position : positions) {
            if (position < minPosition && position > 0) {
                minPosition = position;
            }
        }

        if (minPosition == Integer.MAX_VALUE)
            minPosition = 0;
        return minPosition;
    }

    /* 
     * Bitwise & of each byte in the two arrays.
     * Both arrays are of same length. In order
     * to be memory efficient the result is in
     * the third parameter.
    */
    static byte[] and(byte[] bytes, byte[] bytes2) throws IOException {
        DataInputBuffer bufIn = new DataInputBuffer();
        bufIn.reset(bytes, 0, bytes.length);
        CommitLogHeader clHeader = CommitLogHeader.serializer().deserialize(bufIn);
        byte[] clh = clHeader.getBitSet();

        bufIn.reset(bytes2, 0, bytes2.length);
        CommitLogHeader clHeader2 = CommitLogHeader.serializer().deserialize(bufIn);
        byte[] clh2 = clHeader2.getBitSet();

        byte[] result = new byte[clh.length];
        for (int i = 0; i < clh.length; ++i) {
            result[i] = (byte) (clh[i] & clh2[i]);
        }

        return result;
    }

    static boolean isZero(byte[] bytes) {
        for (byte b : bytes) {
            if (b == 1)
                return false;
        }
        return true;
    }

    private byte[] header_ = ArrayUtils.EMPTY_BYTE_ARRAY;
    private int[] position_ = new int[0];

    CommitLogHeader(int size) {
        header_ = new byte[size];
        position_ = new int[size];
    }

    /*
     * This ctor is used while deserializing. This ctor
     * also builds an index of position to column family
     * Id.
    */
    CommitLogHeader(byte[] header, int[] position) {
        header_ = header;
        position_ = position;
    }

    CommitLogHeader(CommitLogHeader clHeader) {
        header_ = new byte[clHeader.header_.length];
        System.arraycopy(clHeader.header_, 0, header_, 0, header_.length);
        position_ = new int[clHeader.position_.length];
        System.arraycopy(clHeader.position_, 0, position_, 0, position_.length);
    }

    byte get(int index) {
        return header_[index];
    }

    int getPosition(int index) {
        return position_[index];
    }

    void turnOn(int index, long position) {
        turnOn(header_, index, position);
    }

    void turnOn(byte[] bytes, int index, long position) {
        bytes[index] = (byte) 1;
        position_[index] = (int) position;
    }

    void turnOff(int index) {
        turnOff(header_, index);
    }

    void turnOff(byte[] bytes, int index) {
        bytes[index] = (byte) 0;
        position_[index] = 0;
    }

    boolean isSafeToDelete() throws IOException {
        return isSafeToDelete(header_);
    }

    boolean isSafeToDelete(byte[] bytes) throws IOException {
        for (byte b : bytes) {
            if (b == 1)
                return false;
        }
        return true;
    }

    byte[] getBitSet() {
        return header_;
    }

    int[] getPositions() {
        return position_;
    }

    void zeroPositions() {
        int size = position_.length;
        position_ = new int[size];
    }

    void and(CommitLogHeader commitLogHeader) {
        byte[] clh2 = commitLogHeader.header_;
        for (int i = 0; i < header_.length; ++i) {
            header_[i] = (byte) (header_[i] & clh2[i]);
        }
    }

    byte[] toByteArray() throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(bos);
        CommitLogHeader.serializer().serialize(this, dos);
        return bos.toByteArray();
    }

    public String toString() {
        StringBuilder sb = new StringBuilder("");
        for (byte b : header_) {
            sb.append(b);
            sb.append(" ");
        }
        sb.append(" | ");
        for (int position : position_) {
            sb.append(position);
            sb.append(" ");
        }
        return sb.toString();
    }
}

class CommitLogHeaderSerializer implements ICompactSerializer<CommitLogHeader> {
    public void serialize(CommitLogHeader clHeader, DataOutputStream dos) throws IOException {
        dos.writeInt(clHeader.getBitSet().length);
        dos.write(clHeader.getBitSet());
        int[] positions = clHeader.getPositions();

        for (int position : positions) {
            dos.writeInt(position);
        }
    }

    public CommitLogHeader deserialize(DataInputStream dis) throws IOException {
        int size = dis.readInt();
        byte[] bitFlags = new byte[size];
        dis.readFully(bitFlags);

        int[] position = new int[size];
        for (int i = 0; i < size; ++i) {
            position[i] = dis.readInt();
        }

        return new CommitLogHeader(bitFlags, position);
    }
}