com.buaa.cfs.nfs3.FileHandle.java Source code

Java tutorial

Introduction

Here is the source code for com.buaa.cfs.nfs3.FileHandle.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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.buaa.cfs.nfs3;

import com.buaa.cfs.common.oncrpc.XDR;
import org.apache.commons.io.Charsets;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
 * This is a file handle use by the NFS clients. Server returns this handle to the client, which is used by the client
 * on subsequent operations to reference the file.
 */
public class FileHandle {
    private static final Log LOG = LogFactory.getLog(FileHandle.class);
    private static final String HEXES = "0123456789abcdef";
    private static final int HANDLE_LEN = 32;
    private byte[] handle; // Opaque handle
    private long fileId = -1;

    public FileHandle() {
        handle = null;
    }

    /**
     * Handle is a 32 bytes number. For HDFS, the last 8 bytes is fileId.
     */
    public FileHandle(long v) {
        fileId = v;
        handle = new byte[HANDLE_LEN];
        handle[0] = (byte) (v >>> 56);
        handle[1] = (byte) (v >>> 48);
        handle[2] = (byte) (v >>> 40);
        handle[3] = (byte) (v >>> 32);
        handle[4] = (byte) (v >>> 24);
        handle[5] = (byte) (v >>> 16);
        handle[6] = (byte) (v >>> 8);
        handle[7] = (byte) (v >>> 0);
        for (int i = 8; i < HANDLE_LEN; i++) {
            handle[i] = (byte) 0;
        }
    }

    public FileHandle(String s) {
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("MD5");
            handle = new byte[HANDLE_LEN];
        } catch (NoSuchAlgorithmException e) {
            LOG.warn("MD5 MessageDigest unavailable.");
            handle = null;
            return;
        }

        byte[] in = s.getBytes(Charsets.UTF_8);
        digest.update(in);

        byte[] digestbytes = digest.digest();
        for (int i = 0; i < 16; i++) {
            handle[i] = (byte) 0;
        }

        for (int i = 16; i < 32; i++) {
            handle[i] = digestbytes[i - 16];
        }
    }

    public boolean serialize(XDR out) {
        out.writeInt(handle.length);
        out.writeFixedOpaque(handle);
        return true;
    }

    private long bytesToLong(byte[] data) {
        ByteBuffer buffer = ByteBuffer.allocate(8);
        for (int i = 0; i < 8; i++) {
            buffer.put(data[i]);
        }
        buffer.flip();// need flip
        return buffer.getLong();
    }

    public boolean deserialize(XDR xdr) {
        if (!XDR.verifyLength(xdr, 32)) {
            return false;
        }
        int size = xdr.readInt();
        handle = xdr.readFixedOpaque(size);
        fileId = bytesToLong(handle);
        return true;
    }

    private static String hex(byte b) {
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
        return strBuilder.toString();
    }

    public long getFileId() {
        return fileId;
    }

    public byte[] getContent() {
        return handle.clone();
    }

    @Override
    public String toString() {
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < handle.length; i++) {
            s.append(hex(handle[i]));
        }
        return s.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof FileHandle)) {
            return false;
        }

        FileHandle h = (FileHandle) o;
        return Arrays.equals(handle, h.handle);
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(handle);
    }
}